Hibernate Validator 简单介绍

457 阅读3分钟

在程序开发中,经常要对数据进行校验后再进行业务处理。如果在业务代码中进行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;
}
  1. 校验方式有两种:

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之间
    }
}

通用约束

下面两个表引用自:developer.ibm.com/zh/technolo…

  1. Bean Validation 中内置的 constraint
Constraint详细信息
@Null被注释的元素必须为 null
@NotNull被注释的元素必须不为 null
@AssertTrue被注释的元素必须为 true
@AssertFalse被注释的元素必须为 false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式
  1. Hibernate Validator 附加的 constraint
Constraint详细信息
@Email被注释的元素必须是电子邮箱地址
@Length被注释的字符串的大小必须在指定的范围内
@NotEmpty被注释的字符串的必须非空
@Range被注释的元素必须在合适的范围内

编译器校验工具

直接使用 Hibernate Validator 时,如果开发者错误的使用了约束,例如使用@Range校验Boolean类型的字段。

@Data
public class DataBean {
    @NotNull
    private String name;
    @Range(min = 1, max = 120)
    private Boolean age;
}

在代码执行时,会抛出异常。

UnexpectedTypeException

这种情况下,开发者很容易书写不太容易发现的bug,导致线上问题。可以通过添加hibernate-validator-annotation-processor工具,在编译期就发现潜在错误使用约束的问题。maven依赖为:

<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-validator-annotation-processor</artifactId>
	<version>6.1.5.Final</version>
</dependency>

添加此依赖后,编译时会提示相关的错误信息。

notify