JSR303/JSR-349,hibernate validator,spring validation之间的关系

JSR303是一项标准,JSR-349是其的升级版本,添加了一些新特性,他们规定一些校验规范即校验注解,如@Null,@NotNull,@Pattern,他们位于javax.validation.constraints包下,只提供规范不提供实现。而hibernate-validator是对这个规范的实践(不要将hibernate和数据库orm框架联系在一起),他提供了相应的实现,并增加了一些其他校验注解,如@Email,@Length,@Range等等,他们位于org.hibernate.validator.constraints包下。而万能的spring为了给开发者提供便捷,对hibernate validator进行了二次封装,

使用validation-api,通过注解形式进行数据校验

依赖包含关系

校验注解包含在spring-boot-starter-web里面

1
2
3
4
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

查看spring-boot-starter-web的子依赖:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
      <version>2.2.1.RELEASE</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>tomcat-embed-el</artifactId>
          <groupId>org.apache.tomcat.embed</groupId>
        </exclusion>
      </exclusions>
    </dependency>

子依赖中包含了spring-boot-starter-validation,再查看该依赖的子依赖:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    <dependency>
      <groupId>jakarta.validation</groupId>
      <artifactId>jakarta.validation-api</artifactId>
      <version>2.0.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.hibernate.validator</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.18.Final</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <artifactId>validation-api</artifactId>
          <groupId>javax.validation</groupId>
        </exclusion>
      </exclusions>
    </dependency>

可以发现,该子依赖中包含了validation-api,同时包含了它的实现hibernate-validator

validation-api基本注解

限制 说明
@Null 限制只能为null
@NotNull 限制必须不能为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@FutureOrPresent 限制必须是将来的日期或现在
@PastOrPresent 限制必须是过去的日期或现在
@Past 限制必须是一个过去的日期
@Min(value) 限制必须为一个不小于指定值的数字,@Min and @Max supports primitives and their wrappers.
@Max(value) 限制必须为一个不大于指定值的数字
@Pattern(regrexp) 限制必须符合指定的正则表达式,通过regrexp指定正则表达式
@Size(max,min) 限制字符长度必须在min到max之间,supports String, Collection, Map and arrays
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty@NotBlank只应用于字符串且在比较时会去除字符串的空格(The difference to @NotEmpty is that this constraint can only be applied on character sequences and that trailing white-spaces are ignored.)
@Email(regrexp, flags) 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

注意

1. 对dto(@RequestBody)进行数据校验

直接在dto的类中的属性上加上校验注解。但是仅仅这样的话,该注解不会生效

需要在controller中需要校验的参数前加上@Validated注解:

e.g.

1
2
3
4
5
6
    @PostMapping("/register")
    public ResultEntity register(@Validated 
       		 @RequestBody CustomerRequest customerRequest){
        customerService.register(customerRequest);
        return ResultEntity.succeed();
    }

2. 对GET请求的参数(@RequestParam)进行数据校验

@RequestParam注解的参数通常没有专门的类,需要直接在controller方法的参数处加上校验注解:

1
2
3
4
5
6
		@GetMapping("/check-code")
    public ResultEntity sendCheckCode(@RequestParam
                                      @Email(message = "必须为合法邮箱地址") String email) {
        customerService.sendCheckCode(email);
        return ResultEntity.succeed();
    }

仅仅这样,注解也不会生效。切记需要在controller类上加入@Validated注解才可以生效:

1
2
3
4
5
@Slf4j
@RestController
@Validated  // 对@RequestParam的校验需要在controller上加@Validated注解
@RequestMapping("/customer")
public class CustomerController {

官方文档

https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-builtin-constraints