在我们日常开发过程中,新增一个接口我们就会用到参数校验来校验我们自己写的一个用于接受请求参数的类对象,我们可以用javax.validation包下的@valid注解和java的Bean Validation规范来实现参数校验。
一、Bean Validation
1、JSR(Java Specification Requests):java规范提案,是指向JCP提出新增一个标准化技术规范的请求。任何人都可以提交JSR,向java平台新增API和服务。
JCP(Java Community Process):是一个开放的国际组织,主要由Java开发者以及被授权者组成,职能是发展和更新。CP维护的规范包括J2ME、J2SE、J2EE,XML,OSS,JAIN等。组织成员可以提交JSR(Java Specification Requests),通过特定程序以后,进入到下一版本的规范里面。
2、Bean Validation 是一个运行时的数据验证框架,在验证之后的验证错误信息会被马上返回。为JavaBean验证定义了相应的元数据模型和API。在应用程序中,通过使用 Bean Validation 或是你自己定义的 constraint,例如 @NotNull
, @Max
, @ZipCode
, 就可以确保数据模型(JavaBean)的正确性。constraint 可以附加到字段,getter 方法,类或者接口上面。对于一些特定的需求,用户可以很容易的开发定制化的 constraint。基于(JSR303实现的框架提供的api以及服务)
3、Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
4、JSR、JCP、Bean Validation、Hibernate Validator如何理解四者之间的关联关系?
二、javax.validation包
1、需要使用javax.validation包下的注解@Valid,且实现bean 类的校验,就要引入依赖。
这里我们直接引入hibernate-validator框架依赖就行,javax.validation已经被这个框架依赖了。
如果使用springboot,笔者使用的 2.1.7.RELEASE 版本,其中 spring-boot-starter-web 包中已经引入了 hibernate-validator 6.0.17.RELEASE了,不需要我们手动添加。
三、参数校验的实现方式
1、@Valid + BindingResult + javax.validation.constraints
BindingResult 是 spring 对于 Hibernate-Validator的进一步封装,主要处理 约束违反信息 的处理。也就是当 判断 校验不通过时 所获取的 默认的或者自定义的 错误信息。
使用 @Valid 结合 BindingResult实例,Spring将对被注解的实体进行约束校验,原理是AOP。
2. validator.validate()
springboot 自动将 ValidatorFactory 加载到了IOC容器中,不需要进行配置(注意:SpringMVC 需要进行配置)。我们可以使用自动注入的方式获取 ValidatorFactory接口的实现的实例,进而获取 Validator接口的实现的实例,调用.validate(T var1, Class<?>… var2)方法对 java bean 进行约束检验。基于此,还可以用作AOP切面的开发。
我们一般使用第一种方法做校验,因为可以减少重复量等。
具体实现:
①在controller接口类中,在请求参数的类型前面加上@Valid注解后,这个类接收到的请求参数就会被校验
②在这个类中加上自定义校验注解
③定义自定义注解
④
@Constraint(validatedBy = UserPwdValidImpl.class)
加上注解指定实现校验逻辑的类,在这个类中要实现ConstraintValidator<A extends Annotation, T> 复写initialize isValid两个方法。
public class UserPwdValidImpl implements ConstraintValidator<UserPwdValid, String> {
private List<Pattern> patterns;
private boolean allowEmpty;
private String username;
private int pwdMinLen;
private int pwdMaxLen;
@Override
public void initialize(UserPwdValid constraintAnnotation) {
allowEmpty = constraintAnnotation.allowEmpty();
username = constraintAnnotation.userName();
pwdMinLen = constraintAnnotation.pwdMinLen();
pwdMaxLen = constraintAnnotation.pwdMaxLen();
patterns = new ArrayList<>();
for (String userPwdPattern : PatternConst.USER_PWD_PATTERNS) {
patterns.add(Pattern.compile(userPwdPattern));
}
}
@Override
public boolean isValid(String pwd, ConstraintValidatorContext constraintValidatorContext) {
if (StringUtils.isEmpty(pwd)) {
if (this.allowEmpty) {
return true;
}
Exceptions.throwIllegalParam(FaultMsgConst.COMMON_MSG + FaultMsgConst.USER_PWD_FAULT_MESSAGE, "pwd");
}
return pwdCharChcek(pwd);
}
本文是自己的学习笔记,如有错误欢迎指出交流!