在程序开发中,经常要对数据进行校验后再进行业务处理。如果在业务代码中进行Bean的字段校验,会使得代码变的十分繁琐。 JSR303 - Bean Validation 为JavaBean的验证定义了相关的元数据模型和API。
This JSR will define a meta-data model and API for JavaBeanTM validation based on annotations, with overrides and extended meta-data through the use of XML validation descriptors.
在java 8 之后,又推出了 JSR380 - Bean Validation 2.0。
This JSR aims at evolving the Bean Validation specification by leveraging Java 8 language constructs for the purposes of validation.
Hibernate Validator 是 Bean Validation 的实现,Hibernate Validator 内置了 JSR303/JSR380 中所有的 constraint 的实现,还额外提供了很多自定义的 constraint。
快速使用
导入依赖
spring-boot-starter-web中集成了Hibernate Validator工具,无需再额外引用。
<!-- spring boot 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
maven依赖为:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.9.Final</version>
</dependency>
使用方式
1. 在要校验的Bean的字段上添加注解
@Data
public class User {
@NotNull(message = "name 不能为空")
private String name;
@Range(min = 1, max = 120)
private Integer age;
}
2. 校验方式有两种:
1)在要校验的Bean前添加 @Valid或者 @Validated注解;
@RestController
@RequestMapping("/valid/api")
public class ValidatorController {
Gson gson = new Gson();
@PostMapping("/user")
public String addUser(@Validated @RequestBody User bean, BindingResult result) {
System.out.println("res:::" + gson.toJson(result));
return gson.toJson(bean);
}
}
result的数据为:
"target": {
"name": "gavin",
"age": 140
},
"autoGrowNestedPaths": true,
"autoGrowCollectionLimit": 256,
"objectName": "user",
"messageCodesResolver": {
"prefix": "",
"formatter": "PREFIX_ERROR_CODE"
},
"errors": [
{
"field": "age",
"rejectedValue": 140,
"bindingFailure": false,
"objectName": "user",
"codes": [
"Range.user.age",
"Range.age",
"Range.java.lang.Integer",
"Range"
],
"arguments": [
{
"codes": [
"user.age",
"age"
],
"defaultMessage": "age"
},
120,
1
],
"defaultMessage": "需要在1和120之间"
}
],
"fieldTypes": {},
"fieldValues": {},
"suppressedFields": [],
"nestedPath": "",
"nestedPathStack": []
}
2)通过 Validation.buildDefaultValidatorFactory();
public class ValidatorJunitTest {
@Test
public void validatorTest() {
User user = User.builder().name("gavin").age(130).build();
Set<ConstraintViolation<User>> validRes = Validation
.buildDefaultValidatorFactory()
.getValidator()
.validate(user);
List<String> res = validRes
.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList());
String msg = String.join(",", res);
System.out.println("res:" + msg); // 输出:res:需要在1和120之间
}
}
通用约束
下面两个表引用自:https://developer.ibm.com/zh/technologies/java/articles/j-lo-jsr303/
1、Bean Validation 中内置的 constraint
2、Hibernate Validator 附加的 constraint
编译器校验工具
直接使用 Hibernate Validator 时,如果开发者错误的使用了约束,例如使用 @Range 校验Boolean类型的字段。
@Data
public class DataBean {
@NotNull
private String name;
@Range(min = 1, max = 120)
private Boolean age;
}
在代码执行时,会抛出异常。
这种情况下,开发者很容易书写不太容易发现的bug,导致线上问题。可以通过添加 hibernate-validator-annotation-processor工具,在编译期就发现潜在错误使用约束的问题。maven依赖为:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.1.5.Final</version>
</dependency>
添加此依赖后,编译时会提示相关的错误信息。