SpringBoot2 学习笔记08 Validation 参数校验

本文含有: SpringBoot2 Validation 全局异常捕获 注解 分组校验

简单案例

https://github.com/eezd/cli-template/blob/main/springboot2-template/eezd-common/pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • 新建一个名为 PersonDTO 的文件
package com.eezd.main.web.dto;

import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class PersonDTO {
    @NotBlank(message = "name 姓名不能为空")
    private String name;

    @NotNull(message = "age 年龄不能为空")
    @Min(value = 0, message = "年龄不能小于0")
    private Integer age;

    @NotNull(message = "gender 性别不能为空")
    private Integer gender;
}

  • 创建一个 Controller
@PostMapping("/test1")
public Object save(@Validated @RequestBody PersonDTO person, BindingResult bindingResult) {
    System.out.println(bindingResult);
    if (bindingResult.hasErrors()) {
        List<FieldError> fieldErrorList = bindingResult.getFieldErrors();
        Map<String, String> map = new HashMap<>(fieldErrorList.size());
        fieldErrorList.forEach(item -> {
            String field = item.getField(); // 字段名
            String message = item.getDefaultMessage(); // 错误信息
            map.put(field, message);
        });
        return map;
    } else {
        // 伪代码
        // personService.save(person);
    }
    return "YES";
}
  • 发送一个 curl 请求
curl --location --request POST 'http://localhost:8080/test1' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "张三"
}'
  • 返回
{
    "gender": "gender 性别不能为空",
    "age": "age 年龄不能为空"
}

全局异常捕获

如果你不希望每次都在开头写那堆捕获代码,那就可以通过全局异常捕获

https://github.com/eezd/cli-template/blob/main/springboot2-template/eezd-main/src/main/java/com/eezd/main/core/exception/GlobalExceptionHandler.java

package com.eezd.main.core.exception;

/**
 * 全局异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class)
    public AjaxResult handleBindException(BindException e) {
        log.error(e.getMessage());
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return AjaxResult.error(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage());
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return AjaxResult.error(message);
    }

}

  • 创建一个 Controller
@PostMapping("/test2")
public AjaxResult test(@Validated @RequestBody PersonDTO person) {
    return AjaxResult.success("YES");
}
  • 使用curl测试
curl --location --request POST 'http://localhost:8080/test2' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "张三"
}'

注解

判断为空

  • @NotBlank: 不为null, 去除前后空格后长度不为0
    • 支持类型: CharSequence (字符串)
  • @NotEmpty: 不为null, 且长度不为0
    • 支持类型: CharSequence,Collection,Map,Arrays

@NotBlank@NotEmpty 的区别是: 前者会对字符串进行 trim() 操作删除空格, 而后者是直接对长度进行判断。

  • @Null: 限制元素是 null
  • @NotNull: 限制元素不是 null
  • @AssertFalse: 限制元素是 false
  • @AssertTrue: 限制元素是 true

限制长度

下面是限制长度

  • @Length(min=下限, max=上限):支持验证字符串长度
  • @Size(min=最小值, max=最大值): 支持字符串,集合,映射和数组。

限制数值

限制大小

  • @Max(value=)@Min(value=): 限制 整数 的是否大于等于/小于等于
  • @Range(min=最小值, max=最大值): 限制数字范围
  • @DecimalMax(value=n)@DecimalMin(value=n): 限制 浮点数
  • @Digits(integer=整数位数, fraction=小数位数): 限制整数位数和小数位数上限

时间检查

  • @Future: 必须是将来的日期
  • @FutureOrPresent: 必须是将来的日期, 或当前日期
  • @Past: 必须是过去的日期
  • @PastOrPresent: 必须是过去的日期, 或当前日期

其他

  • @Email 检查是否一个合法的邮箱地址
  • @Pattern 检查是否符合指定的正则规则
@Data
public class PersonDTO {
    @NotBlank(message = "name 姓名不能为空")
    private String name;

    @NotNull(message = "age 年龄不能为空")
    @Min(value = 0, message = "年龄不能小于0")
    private Integer age;

    @NotNull(message = "gender 性别不能为空")
    private Integer gender;

    @Email(regexp = RegularConstant.EMAIL, message = "email 邮箱格式不正确")
    private String email;

    @Pattern(regexp = RegularConstant.PHONE, message = "phone 手机号格式不正确")
    private String phone;

    @Past(message = "birthday 生日日期有误")
    private LocalDate birthday;
}

  • 接下来是限制 email 和 phone
public class RegularConstant {  
public static final String EMAIL = "^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";  
public static final String PHONE = "^1[0-9]{10}$";  
}

分组校验

  • 不同请求使用不同的校验规则, 通过组别进行分开
@Data
public class Person {

    @NotBlank(message = "name 姓名不能为空", groups = AddGroup.class)
    private String name;

    @NotNull(message = "age 年龄不能为空", groups = UpdateGroup.class)
    @Min(value = 0, message = "年龄不能小于0")
    private Integer age;

    @NotNull(message = "gender 性别不能为空", groups = {AddGroup.class, UpdateGroup.class})
    private Integer gender;

    @NotBlank(message = "email 邮箱不能为空", groups = Default.class)
    @Email(regexp = RegularConstant.EMAIL, message = "email 邮箱格式不正确", groups = Default.class)
    private String email;

    @NotBlank(message = "phone 手机号不能为空", groups = UpdateGroup.class)
    @Pattern(regexp = RegularConstant.PHONE, message = "phone 手机号格式不正确")
    private String phone;

    @Past(message = "birthday 生日日期有误")
    private LocalDate birthday;
}
  • @Validated 添加上组别就可以验证了
@PostMapping("/test2")
public AjaxResult test(@Validated(AddGroup.class) @RequestBody PersonDTO person) {
    return AjaxResult.success("YES");
}
Licensed under CC BY-NC-SA 4.0
本博客已稳定运行
发表了53篇文章 · 总计28.17k字
使用 Hugo 构建
主题 StackJimmy 设计