在项目中,接收到前端或者其它客户端的调用请求时,需要对传入的参数进行校验。完成这些校验最原始的做法就是编写代码一个个参数进行判断,如判断是否为空、长度是否符合要求、格式是否符合要求等;对于一些简单的输入还好,越复杂的输入,这些校验的代码及逻辑越长,而且在校验失败后组装的返回消息也是因人而异,导致同一项目里面校验失败后返回的消息不统一,最终结果就是用户体验较差。
JSR-303为这类校验提供了一个规范,并在JDK1.6起即提供了Validation包,其中包含了关键的ValidatorFactory及Validator、常用校验注解等内容。Hibernate又在其基础上提供了一个实现。注意这个实现与Hibernate数据库读写中间件无任何关联。
一般项目中都是直接使用Hibernate Validator来进行校验。
1. 简单示例
先来看下单个应用程序如何进行校验。
1.1 实体类
public class TestEntity {
@Size(min = 1, max = 10)
private String msg;
@Size(min = 1, max = 20)
private String name;
@Max(12)
@Min(10)
private int age;
@Email
@NotNull
private String email;
@Pattern(regexp = "\\d+")
private String test;
...
}
1.2 校验
TestEntity testEntity = new TestEntity();
testEntity.setAge(11);
testEntity.setMsg("22");
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
System.out.println(validatorFactory);
Validator validator = validatorFactory.getValidator();
System.out.println(validator.validate(testEntity));
其中主要涉及到ValidatorFactory及Validator两个对象;由于测试工程中包含有hibernate的Validation,因此打印结果如下:
...
org.hibernate.validator.internal.engine.ValidatorFactoryImpl@ba8d91c
...
[ConstraintViolationImpl{
interpolatedMessage='个数必须在1和10之间', propertyPath=msg, rootBeanClass=class com.liuqi.learn.entity.TestEntity, messageTemplate='{javax.validation.constraints.Size.message}'}, ConstraintViolationImpl{
interpolatedMessage='不能为null', propertyPath=email, rootBeanClass=class com.liuqi.learn.entity.TestEntity, messageTemplate='{javax.validation.constraints.NotNull.message}'}]
2 与Spring集成
Spring 中提供了LocalValidatorFactoryBean
的实现,它实现了ValidatorFactory接口及JDK中的Validator接口;当将该对象的实例注入容器后,如果Classpath中包含有Hibernate Validator等校验框架时,将会自动完成校验框架的初始化。
2.1 配置
配置主要是需要将LocalValidatorFactoryBean的实例注入到Spring容器中去,有两种方式:
A. 通过Bean注入
@Configuration
public class ValidationConfig {
@Bean
public Validator validator() {
return new LocalValidatorFactoryBean();
}
}
B. 通过WebMvcConfigurer进行配置
@Configuration
public class ValidationConfig implements WebMvcConfigurer {
@Override
public Validator getValidator() {
return new LocalValidatorFactoryBean();
}
}
2.2 使用
2.2.1 通过Validator直接使用
@Autowired
private Validator validator;
@GetMapping("/validation"