参考资料
校验字符串日期的格式
import org.springframework.util.ObjectUtils;
import javax.validation.*;
import java.lang.annotation.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
// 当我们用javaDoc生成API文档时,将该注解记录到API文档中。
@Documented
// 该注解生效的位置(FIELD: 生效在字段上)
@Target({ ElementType.FIELD })
// 注解生效的阶段(RUNTIME: 运行时)
@Retention(RetentionPolicy.RUNTIME)
// 处理自定义注解的验证逻辑
@Constraint(validatedBy = {ValidateDateString.StrictDateStringValidator.class})
public @interface ValidateDateString {
// 参数
String msgArgs() default "";
// 格式
String pattern() default "yyyy/MM/dd";
// 校验信息,不能省略
String message() default "{1004E}";
// 分组check,不能省略
Class<?>[] groups() default {};
// 作用暂时未知,不能省略
Class<? extends Payload>[] payload() default {};
// 使用内部类进行校验逻辑书写;还可以把校验的逻辑单独创建一个类,然后将.class文件通过@Constraint注解引入
class StrictDateStringValidator implements ConstraintValidator<ValidateDateString, String> {
private String pattern;
@Override
public void initialize(ValidateDateString validStrictDateString) {
this.pattern = validStrictDateString.pattern();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
try {
if (ObjectUtils.isEmpty(value)) {
return true;
}
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
// 设置非严格解析日期
sdf.setLenient(false);
sdf.parse(value);
} catch (ParseException e) {
return false;
}
return true;
}
}
}
作用于注解上,用于当
多个校验注解
作用于自定义注解
的时候的校验逻辑
- @ConstraintComposition(CompositionType.AND): 必须同时满足多个注解的条件才算校验通过
- @ConstraintComposition(CompositionType.OR): 只要满足任意一个注解的条件,就算校验通过
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@Documented
// ❗❗❗当引入外界注解check的时候,此注解不能省略,否则会报错
@Constraint(validatedBy = {})
@ConstraintComposition(CompositionType.AND)
// 引入的校验注解: 非空校验
@NotEmpty
// 引入的校验注解: 正则校验,必须为半角数字
@Pattern(regexp = "[0-9]*")
@ReportAsSingleViolation
public @interface ValidateHalfNumeric {
String message() default "{1005E}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
校验age是否为半角数字
import lombok.Data;
@Data
public class Test4Form {
@ValidateHalfNumeric
private String age;
}
⏹age为空: 不满足非空check,无法通过校验
⏹age为非半角数字: 不满足正则check,无法通过校验
⏹age为空: 仅满了正则check就通过校验
⏹age为非半角数字: 仅满足了非空check就通过校验
当引入的多个校验注解同时作用于自定义注解时,才会起作用.如果不引入外界校验注解到自定义校验注解的话,
@ReportAsSingleViolation
注解没有效果.
- 若待校验的数据不符合引入的校验注解的规则时,错误信息依然显示为自定义注解的.
- 若不添加
@ReportAsSingleViolation
注解的话,则会显示为引入的自定义注解所带的错误信息.
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@Documented
@Constraint(validatedBy = {})
@ConstraintComposition(CompositionType.AND)
@NotEmpty
@Pattern(regexp = "[0-9]*")
//
@ReportAsSingleViolation
public @interface ValidateHalfNumeric {
String message() default "{1005E}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
待校验数据不满足引入的@Pattern
注解条件,错误信息为自定义@ValidateHalfNumeric
注解自带的
若不添加@ReportAsSingleViolation
注解的话,错误信息为@Pattern
注解所携带的
组合使用,让注解可多次作用于同一属性上
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@Documented
@Constraint(validatedBy = {})
@ConstraintComposition(CompositionType.AND)
@NotEmpty
@Pattern(regexp = "[0-9]*")
@ReportAsSingleViolation
// ⭕⭕⭕标记该注解是否可重复使用
@Repeatable(ValidateHalfNumeric.List.class)
public @interface ValidateHalfNumeric {
String message() default "{1005E}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
// 注解可以List的形式
@Target({ FIELD })
@Retention(RUNTIME)
@Documented
public @interface List {
ValidateHalfNumeric[] value();
}
}
import lombok.Data;
import javax.validation.groups.Default;
@Data
public class Test4Form {
// 使用了同一个校验注解,不同的分组的错误消息不同
@ValidateHalfNumeric(message = "{1005E}", groups = {AgeGroup.class})
@ValidateHalfNumeric(message = "{1008E}", groups = {Default.class})
private String age;
public interface AgeGroup { }
}
import lombok.Data;
@Data
public class Test4Form {
// 通过List的方式指定多个校验注解,根据不同的分组显示不同的校验消息
@ValidateHalfNumeric.List({
@ValidateHalfNumeric(message = "{1005E}", groups = {AgeGroup.class}),
@ValidateHalfNumeric(message = "{1008E}", groups = {Default.class})
})
private String age;
}
我们自定义的
@ValidateSize
注解使用了JDK自带的@Size
注解进行校验,
使用@OverridesAttribute
注解覆盖重写原@Size注解中的属性
import javax.validation.Constraint;
import javax.validation.OverridesAttribute;
import javax.validation.Payload;
import javax.validation.constraints.Size;
import javax.validation.ReportAsSingleViolation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
@Documented
@Constraint(validatedBy = {})
@ReportAsSingleViolation
@Size
public @interface ValidateSize {
String msgArgs() default "";
String message() default "{1006E}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
// 覆盖重写@Size注解中的属性
@OverridesAttribute(constraint = Size.class, name = "min")
int min() default 0;
@OverridesAttribute(constraint = Size.class, name = "max")
int max() default Integer.MAX_VALUE;
}