@GroupSequence简单使用

2021-03-13   


@GroupSequence简单使用

场景

  对于一个表示时间的字符串入参需要同时保证不能为空并且符合时间格式校验。不能为空可以直接使用@NotBlank注解实现,时间格式的校验也可以自行编写自定义注解实现。问题来了,如何控制这2个注解的校验顺序呢?我当然希望优先校验完不为空后,再来校验格式问题。这个时候@就轮到GroupSequence登场了。

简介

  默认情况下,多个约束的校验顺序是随机的,当我们想控制校验的顺序时@GroupSequence可以说非常有用。它提供了指定多个Group的顺序能力。

demo
  1. 自定义校验注解及校验类
@Constraint(validatedBy = {DateFormatValidator.class})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckDateFormat {

    String format() default "yyyy-MM-dd HH:mm:ss";

    String message() default "时间格式错误";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}
public class DateFormatValidator implements ConstraintValidator<CheckDateFormat, String> {

    private String format;
    private String message;
    private Class<?>[] groups;

    @Override
    public void initialize(CheckDateFormat constraintAnnotation) {
        this.format = constraintAnnotation.format();
        this.message = constraintAnnotation.message();
        this.groups = constraintAnnotation.groups();
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        //根据自己需求来,这边当为空时不进行格式校验
        if (StringUtils.isBlank(s)) {
            return true;
        }
        try {
            //是否可以转换为时间格式
            LocalDateTimeUtils.formatTimeStr(s, format);
            return true;
        } catch (Exception e) {
            constraintValidatorContext.disableDefaultConstraintViolation();
            constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();
            return false;
        }
    }
}
  1. 需要校验的入参DTO
@Data
public class QueryListDTO {

    @NotBlank(message = "时间不能为空", groups = Default.class)
    @CheckDateFormat(message = "时间格式错误", groups = FormatGroup.class)
    private String time;

    public interface FormatGroup {
    }

    //指定顺序,先Default,再FormatGroup
    @GroupSequence({Default.class, FormatGroup.class})
    public interface Group {
    }

}
  1. controller使用@Validated指定Group
    @PostMapping("/test")
    public void test(@RequestBody @Validated(value = QueryListDTO.Group.class) QueryListDTO queryListDTO){
        //todo
    }
其他

  个人不是很喜欢在service层做参数的业务校验,所以一般都借助validation来提前校验参数。像这种关于时间格式的校验很明显就是可以造了轮子大家公用的~简单方便。

Q.E.D.