内部类级联校验

  1. 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
    @Getter
    @Setter
    @ToString
    public class Person {
    @NotNull
    private String name;
    @NotNull
    @Range(min = 10, max = 40)
    private Integer age;
    @NotNull
    @Size(min = 3, max = 5)
    private List<String> hobbies;
    // 级联校验
    @Valid
    @NotNull
    private Child child;
    public static class Child {
    @NotNull
    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);
    }
    }
  2. 输出结果:
    1
    2
    3
    hobbies 个数必须在3和5之间: [足球, 篮球]
    age 需要在10和40之间: 5
    child.name 不能为null: null

分组条件校验

  1. 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);
    }
    }
  2. 实现 DefaultGroupSequenceProvider 接口,getValidationGroups 参数可以使用Object + 反射让它变得更为通用,但本着职责单一原则,不建议这么去做。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public 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;
    }
    }

    校验顺序

  3. 例如校验 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);
    }
    }