Spring Boot 2.x Validation参数校验


编写接口时,为防止非法参数对业务造成影响,需要在Controller层添加参数校验。通过javax.validation的一系列注解可以帮助我们完成参数校验,免去繁琐的逻辑判断。

依赖

根据JSR 380规范,validation-api依赖中包含标准的参数验证API:

Bean Validation 2.0 版本需要Java 8或更高版本。

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.2.Final</version>
</dependency>

Hibernate Validator是参数验证API的具体实现。

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.7.Final</version>
</dependency>

在Spring Boot 2.3.x之前,以上依赖在spring-boot-starter-web中自动引入。 Spring Boot 2.3.x之后,需要手动引入。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

使用场景

入参为实体对象

当入参为实体对象时,在对象上添加@Validated注解,并且实体属性上添加约束注解(如@Size等) 就能实现参数的自动校验。

  1. 实体对象添加@Validated注解
    public R<Boolean> save(@RequestBody @Validated User user) {}
  2. 实体属性上添加约束注解。
    import javax.validation.constraints.AssertTrue;
    import javax.validation.constraints.Max;
    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    import javax.validation.constraints.Email;
    
    public class User {
        
        @NotNull(message = "用户名称不能为空")
        private String name;
    
        @AssertTrue
        private boolean working;
    
        @Size(min = 6, max = 20, message 
          = "密码长度必须是6-20个字符")
        private String password;
    
        @Min(value = 18, message = "年龄最小不超过18")
        @Max(value = 150, message = "年龄最大不超过150")
        private int age;
    
        @Email(message = "邮箱格式不正确")
        private String email;
    
        // ...
    }
  3. 如果不符合验证要求,则将注解属性message的信息作为响应提示信息。
{
    "code": 400,
    "success": true,
    "data": null,
    "msg": "用户名称不能为空"
}

全局异常拦截

添加参数检验全局拦截处理类

@RestControllerAdvice
@Configuration
public class CommonExceptionHandler {

 /**
     * 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<Object> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        return R.fail(ResultCode.PARAM_MISS, message);
    }

    /**
     * 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
     */
    @ExceptionHandler(BindException.class)
    public R<Object> bindExceptionHandler(BindException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        return R.fail(ResultCode.PARAM_MISS, message);
    }

    /**
     * 处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是ConstraintViolationException
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public R constraintViolationExceptionHandler(ConstraintViolationException e) {
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(","));
        return R.fail(ResultCode.PARAM_MISS, message);
    }

}

注解

注解 支持验证类型 说明
@Null 任意类型 验证带注解的属性值是null。
@NotNull 任意类型 验证带注解的属性值不为null。
@NotEmpty String、 Collection、 Map或Array 验证带注解的属性值不为null或空。
@NotBlank String 验证带注解的属性值不为null或空字符,只针对字符串检验。
@AssertTrue Boolean 验证带注解的属性值是true。
@AssertFalse Boolean 验证带注解的属性值是false。
@Size String、 Collection、 Map或Array 验证带注解的属性值的大小介于属性min和max之间。
@Digits BigDecimal、BigInteger、CharSequence、byte, short, int, long以及它们的封装类型 验证带注解的属性值是可接受范围内的数字。
@Min BigDecimal、BigInteger、byte, short, int, long以及它们的封装类型 验证带注解的属性值不小于@Min指定的value值。
@Max 同@Min要求 验证带注解的属性值不大于@Max指定的value值。
@DecimalMin 同@Digits要求 验证带注解的属性值不小于@DecimalMin指定的value值。
@DecimalMax 同@Digits要求 验证带注解属性值不大于@DecimalMax指定的value值。
@Positive 同@Min要求 验证带注解的属性值是正数。
@PositiveOrZero 同@Min要求 验证带注解的属性值是正数或0。
@Negative 同@Min要求 验证带注解的属性值是负数。
@NegativeOrZero 同@Min要求 验证带注解的属性值是负数或0。
@Past java.util.Date、java.util.Calendar、java.time 验证带注解的属性值为过去时间(比当前时间早)。
@PastOrPresent 同@Past要求 验证带注解的属性值为过去时间(比当前时间早)或当前时间。
@Future 同@Past要求 验证带注解的属性值为未来时间(比当前时间晚)。
@FutureOrPresent 同@Past要求 验证带注解的属性值为未来时间(比当前时间晚)或当前时间。
@Pattern String 验证带注解的属性值与指定的正则表达式匹配。
@Email String 验证带注解的属性值是有效的电子邮件地址。

文章作者: 苏叶新城
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 苏叶新城 !
  目录