内部类级联校验
- Person 对象 和 Child 对象,如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Person {
private String name;
private Integer age;
private List<String> hobbies;
// 级联校验
private Child child;
public static class Child {
private String name;
}
public static void main(String[] args) {
Person person = new Person();
person.setName("kp");
person.setAge(5);
person.setHobbies(Arrays.asList("足球","篮球"));
person.setChild(new Child());
Set<ConstraintViolation<Person>> result = Validation.buildDefaultValidatorFactory().getValidator().validate(person);
// 对结果进行遍历输出
result.stream().map(v -> v.getPropertyPath() + " "
+ v.getMessage() + ": " + v.getInvalidValue()).forEach(System.out::println);
}
} - 输出结果:
1
2
3hobbies 个数必须在3和5之间: [足球, 篮球]
age 需要在10和40之间: 5
child.name 不能为null: null
分组条件校验
- Person2 类,当年龄满足分组条件的,那么会校验 hobbies 的集合大小,例如:WhenAge20And30Group组,那么年龄在20~30岁,会校验集合大小是否满足。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36@GroupSequenceProvider(PersonGroupSequenceProvider.class)
@Getter
@Setter
@ToString
public class Person2 {
@NotNull
private String name;
@NotNull
@Range(min = 10, max = 40)
private Integer age;
@NotNull(groups = {WhenAge20And30Group.class, WhenAge30And40Group.class})
@Size(min = 1, max = 2, message = "hobbies 长度 1~2", groups = WhenAge20And30Group.class)
@Size(min = 3, max = 5, message = "hobbies 长度 3~5", groups = WhenAge30And40Group.class)
private List<String> hobbies;
/**
* 定义专属的业务逻辑分组
*/
public interface WhenAge20And30Group {
}
public interface WhenAge30And40Group {
}
public static void main(String[] args) {
Person2 person2 = new Person2();
person2.setName("kp");
person2.setAge(35);
person2.setHobbies(Arrays.asList("足球","羽毛球"));
Set<ConstraintViolation<Person2>> result2 = Validation.buildDefaultValidatorFactory().getValidator().validate(person2);
// 对结果进行遍历输出
result2.stream().map(v -> v.getPropertyPath() + " "
+ v.getMessage() + ": " + v.getInvalidValue()).forEach(System.out::println);
}
} - 实现 DefaultGroupSequenceProvider 接口,getValidationGroups 参数可以使用Object + 反射让它变得更为通用,但本着职责单一原则,不建议这么去做。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class PersonGroupSequenceProvider implements DefaultGroupSequenceProvider<Person2> {
@Override
public List<Class<?>> getValidationGroups(Person2 person) {
List<Class<?>> defaultGroupSequence = new ArrayList<>();
// 这一步不能省,否则 Default 分组都不会执行了,会抛错的
defaultGroupSequence.add(Person2.class);
// 这块判空请务必要做
if (person != null) {
Integer age = person.getAge();
System.err.println("年龄为:" + age + ",执行对应校验逻辑");
if (age >= 20 && age < 30) {
defaultGroupSequence.add(Person2.WhenAge20And30Group.class);
} else if (age >= 30 && age < 40) {
defaultGroupSequence.add(Person2.WhenAge30And40Group.class);
}
}
return defaultGroupSequence;
}
}校验顺序
- 例如校验 A->B->C,先校验A,如果 A 满足条件,则校验 B,B 满足条件,则校验 C,如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29@Data
public class User {
@NotEmpty(message = "firstname may be empty")
private String firstname;
@NotEmpty(message = "middlename may be empty", groups = Default.class)
private String middlename;
@NotEmpty(message = "lastname may be empty", groups = GroupA.class)
private String lastname;
@NotEmpty(message = "country may be empty", groups = GroupB.class)
private String country;
public interface GroupA {
}
public interface GroupB {
}
// 组序列
@GroupSequence({Default.class, GroupA.class, GroupB.class})
public interface Group {
}
public static void main(String[] args) {
User user = new User();
user.setMiddlename("hello");
user.setFirstname("hello");
// 此处指定了校验组是:User.Group.class
Set<ConstraintViolation<User>> result = Validation.buildDefaultValidatorFactory().getValidator().validate(user, User.Group.class);
// 对结果进行遍历输出
result.stream().map(v -> v.getPropertyPath() + " " + v.getMessage() + ": " + v.getInvalidValue()).forEach(System.out::println);
}
}