自定义验证
Hibernate Validate提供了很丰富的内置验证注解。当这些还不能满足你的要求,我们可以自定义验证注解。
比如:我们自定义一个关键字过滤的验证规则注解如下。
1. 编写验证规则注解类
package com.yyoo.springmvc.valid;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {KeyWordValidator.class})
@Documented
@Repeatable(KeyWord.List.class)
public @interface KeyWord {
String message() default "{com.yyoo.springmvc.valid.KeyWord.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
String keyWords() default "";
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
KeyWord[] value();
}
}
几个元注解的解释
- @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE }):定义约束支持的目标元素类型。@KeyWord可用于字段(元素类型FIELD)、JavaBeans 属性以及方法返回值(METHOD)、方法/构造函数参数(PARAMETER)和参数化类型的类型参数(TYPE_USE)。元素类型ANNOTATION_TYPE允许创建构成约束的基础上@KeyWord。
- @Retention(RetentionPolicy.RUNTIME): 该类型的注解将在运行时通过反射的方式可用(我们定义一般都使用该方式)
@Constraint(validatedBy = {KeyWordValidator.class}): 将注解类型标记为约束注解,并指定对应的验证器类为KeyWordValidator(验证器我们在下文定义)。如果约束可以用于多种数据类型,则可以指定多个验证器,每个数据类型一个。 - @Documented: 注解是否将包含在JavaDoc中
- @Repeatable(List.class):表示注解可以在同一个地方重复多次,通常配置不同。List就是我们注解类中的定义的内部注解List。
验证注解有如下几个必要的属性
- message:错误消息属性。我们设置了默认值{com.yyoo.springmvc.valid.KeyWord.message},表示它将读取国际化文件的消息配置
- groups:指定验证组。这必须默认为 Class<?> 类型的空数组。
- payload:Jakarta Bean Validation API 的客户端可以使用该属性将自定义负载对象分配给约束。API 本身不使用此属性。
自定义属性
示例中keyWords属性是我们的自定义属性,可根据自身的需求进行定义。
内部注释List
它允许@CheckCase在同一元素上指定多个 注释,例如使用不同的验证组和消息。虽然可以使用另一个名称,但 Jakarta Bean 验证规范建议使用 List 并使注释成为相应约束类型的内部注释。
2. 定义验证器类KeyWordValidator
package com.yyoo.springmvc.valid;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class KeyWordValidator implements ConstraintValidator<KeyWord,String> {
private String keyWords;
@Override
public void initialize(KeyWord constraintAnnotation) {
// 将注解上初始化的值导入
this.keyWords = constraintAnnotation.keyWords();
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
// 一个简单的规则,如果包含关键字则不通过
if(this.keyWords.contains(s)){
return false;
}
return true;
}
}
javax.validation.ConstraintValidator<A extends Annotation, T>接口
每个自定义验证器,都需要实现该接口
initialize方法提供验证器的初始化,如我们的示例,就是将我们在使用注解的时候赋值的keyWords属性,将其值导入到我们的当前验证器。然后在isValid方法中使用。
ConstraintValidatorContext
我们的示例没有使用该参数。但比如我们需要在验证器中定义一些其他的提示信息,我们可以如下使用:
if ( !isValid ) {
constraintContext.disableDefaultConstraintViolation();
constraintContext.buildConstraintViolationWithTemplate(
"{com.yyoo.springmvc.valid.KeyWord.other.message}"
)
.addConstraintViolation();
}
验证示例
@NotNull
@KeyWord(keyWords = "name,age",message = "姓名不能包含{keyWords}",groups = GroupThree.class)
private String name;
当name属性包含name、age属性时将会提示姓名不能包含name、age
更多的高级用法和功能(如自定义验证注解、自定义交叉验证等)请参考Hibernate Validator
上一篇:006-Spring MVC参数验证2-分组验证
下一篇:008-Spring MVC ViewResolver视图解析器