自定义 Validation 注解
在 Java 后端的数据校验常用 @NotNull
、@NotEmpty
或 @Size
等注解进行校验,但标应准的验证注解是很局限的,在一些特殊要求的验证中并不能满足需求。
自定义校验注解
要想实现业务用特定需求的验证只用定义一个注解和对应的校验类既可,下面实现一个非空字符串验证注解。
1. 定义注解
1 |
|
注解中要注意的是 @Constraint
注解用于指定验证的实现类。
2. 定义注解校验类
注解校验类需实现 ConstraintValidator<A extends Annotation, T>
接口,该接口有两个方法。
1 | void initialize(A constraintAnnotation); |
initialize
方法用于在校验的时候初始化一些参数,比如注解的信息。对于同一个注解(一个验证实例)只会调用一次,而不是每次校验都会调用。
1 | boolean isValid(T value, ConstraintValidatorContext context); |
isValid
方法里实现真正的校验逻辑,验证通过返回 true。value
是注解的对象,如果注解到类上,则对应类的对象。 context
是验证的上下文,可以将验证的结果存放在这里,如果验证不通过,错误信息也应该放在里面。
1 | public class NotBlankCharValidator implements ConstraintValidator<NotBlankChar, String> { |
错误信息中的 Constraint Violation
Constraint Violation
指的是验证违反信息,每调用一次 addConstraintViolation
会增加一条新的记录。 假设有如下对象:
1 | public class User { |
- 在
User.addresses
属性上注解,User.addresses
验证报错
直接使用默认的 path,因为注解直接打在 User.addresses 上,默认就是 addresses 属性
1 | context.buildConstraintViolationWithTemplate( "this detail is wrong" ) |
- 在
Address
的类上注解,street 报错
注解打在 Address
类上,错误的属性就是 默认+street
1 | context.buildConstraintViolationWithTemplate( "this detail is wrong" ) |
- 在
User.addresses
属性上注解,取addresses
map 里 key 为home
的验证报错
1 | // addresses["home"] |
- 在
User
类上注解,addresses["home"].country.name
验证报错
1 | \\ addresses["home"].country.name |
上下文变量
在 message 中可以用 ${}
取得上下文的变量,通过以下方法可以设置这些变量
1 | HibernateConstraintValidatorContext validatorContext = context.unwrap(HibernateConstraintValidatorContext.class); |
自定义 Validation 注解
https://blog.imoe.tech/2018/06/15/10-custom-validation-annotation/