Springboot3实体属性校验

1.使用 Jakarta Validation (原 javax.validation) 注解进行验证:

// 实体类
import jakarta.validation.constraints.*;

@Data
public class UserDTO {
    @NotNull(message = "用户名不能为空")
    @Size(min = 2, max = 20, message = "用户名长度必须在2-20之间")
    private String username;

    @NotBlank(message = "密码不能为空")
    @Size(min = 6, message = "密码长度不能小于6位")
    private String password;

    @Email(message = "邮箱格式不正确")
    private String email;
}

2.在 Controller 中使用 @Valid 或 @Validated 注解:

@RestController
@RequestMapping("/api")
public class UserController {

    @PostMapping("/user")
    public ResponseEntity<?> createUser(@Valid @RequestBody UserDTO userDTO) {
        // 处理业务逻辑
        return ResponseEntity.ok().build();
    }
}

3.修改全局异常处理器,添加参数验证异常处理:

@ControllerAdvice
public class GlobalExceptionHandler {

    // 处理自定义异常
    @ExceptionHandler(CustomException.class)
    public ResponseEntity<Object> handleCustomException(CustomException ex) {
        Map<String, Object> body = new HashMap<>();
        body.put("status", 4001);
        body.put("message", ex.getMessage());
        return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
    }

    // 处理参数验证异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Object> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, Object> body = new HashMap<>();
        List<String> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.toList());

        body.put("status", 4002);
        body.put("message", "参数验证失败");
        body.put("errors", errors);

        return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
    }
}

4.在 pom.xml 中添加依赖:

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

5.常用的验证注解:

@NotNull        // 不能为null
@NotEmpty       // 不能为空,用于集合
@NotBlank       // 不能为空,用于String,会去除前后空格
@Size           // 长度或大小范围
@Min            // 最小值
@Max            // 最大值
@Email          // 邮箱格式
@Pattern        // 正则表达式
@Past           // 必须是过去的日期
@Future         // 必须是将来的日期
@Positive       // 正数
@Negative       // 负数

6.如果需要分组验证,可以这样做:

// 定义验证组
public interface Create {}
public interface Update {}

// 在实体类中使用组
public class UserDTO {
    @NotNull(groups = {Create.class, Update.class})
    private String username;

    @NotNull(groups = Create.class)
    private String password;
}

// 在Controller中指定组
@PostMapping("/user")
public ResponseEntity<?> createUser(@Validated(Create.class) @RequestBody UserDTO userDTO) {
    // ...
}

使用这种方式的优点是:

  1. 代码简洁,易于维护
  2. 验证逻辑与业务逻辑分离
  3. 可以自定义错误消息
  4. 支持分组验证
  5. 可以通过全局异常处理统一处理验证错误

注意事项:

  1. 确保添加了validation依赖
  2. 记得在Controller方法参数上添加@Valid或@Validated注解
  3. 可以根据需要自定义错误消息
  4. 可以组合使用多个注解
  5. 对于复杂的验证逻辑,可以自定义验证注解

我来详细分类说明这些验证注解:

字符串相关的验证注解:

  1. @NotBlank

    • 只能用于String类型
    • 判断字符串不能为null,并且去除首尾空格后长度必须大于0
      @NotBlank(message = "名称不能为空")
      private String name;
  2. @Size

    • 可用于String、Collection、Map、数组
    • 检查字符串长度或集合大小是否在指定范围内
      @Size(min = 2, max = 30, message = "名称长度必须在2-30之间")
      private String name;
  3. @Email

    • 只能用于String类型
    • 验证是否是合法的邮箱格式
      @Email(message = "邮箱格式不正确")
      private String email;
  4. @Pattern

    • 只能用于String类型
    • 使用正则表达式进行验证
      @Pattern(regexp = "^[0-9]{11}$", message = "手机号格式不正确")
      private String phone;

数字相关的验证注解:

  1. @Min

    • 用于数字类型(整数或小数)
    • 验证数字是否大于或等于指定的最小值
      @Min(value = 0, message = "年龄不能小于0")
      private Integer age;
  2. @Max

    • 用于数字类型(整数或小数)
    • 验证数字是否小于或等于指定的最大值
      @Max(value = 150, message = "年龄不能大于150")
      private Integer age;
  3. @Positive

    • 用于数字类型
    • 验证数字是否为正数(大于0)
      @Positive(message = "数量必须为正数")
      private Integer quantity;
  4. @PositiveOrZero

    • 用于数字类型
    • 验证数字是否为正数或0
      @PositiveOrZero(message = "数量必须大于或等于0")
      private Integer quantity;
  5. @Negative

    • 用于数字类型
    • 验证数字是否为负数(小于0)
      @Negative(message = "温度必须为负数")
      private Integer temperature;
  6. @NegativeOrZero

    • 用于数字类型
    • 验证数字是否为负数或0
      @NegativeOrZero(message = "温度必须小于或等于0")
      private Integer temperature;
  7. @DecimalMin

    • 用于数字类型
    • 验证数字是否大于或等于指定的最小值(可以指定是否包含边界值)
      @DecimalMin(value = "0.1", message = "比例必须大于0.1")
      private BigDecimal ratio;
  8. @DecimalMax

    • 用于数字类型
    • 验证数字是否小于或等于指定的最大值(可以指定是否包含边界值)
      @DecimalMax(value = "1.0", message = "比例必须小于1.0")
      private BigDecimal ratio;

通用的验证注解:

  1. @NotNull

    • 可用于任何类型
    • 验证属性值不能为null
      @NotNull(message = "对象不能为null")
      private Object obj;
  2. @NotEmpty

    • 可用于String、Collection、Map、数组
    • 验证对象不能为null且不能为空(长度或大小必须大于0)
      @NotEmpty(message = "列表不能为空")
      private List<String> items;

实际使用示例:

@Data
public class UserDTO {
    // 字符串验证
    @NotBlank(message = "用户名不能为空")
    @Size(min = 2, max = 20, message = "用户名长度必须在2-20之间")
    private String username;

    // 数字验证
    @Min(value = 0, message = "年龄不能小于0")
    @Max(value = 150, message = "年龄不能大于150")
    private Integer age;

    // 邮箱验证
    @Email(message = "邮箱格式不正确")
    private String email;

    // 手机号验证
    @Pattern(regexp = "^[0-9]{11}$", message = "手机号格式不正确")
    private String phone;

    // 金额验证
    @PositiveOrZero(message = "金额必须大于或等于0")
    private BigDecimal amount;
}

这些注解可以组合使用,以实现更复杂的验证需求。同时,你也可以自定义错误消息,使用占位符来实现更灵活的提示信息。

分类: 标签: SpringBoot3 属性校验 Jakarta Validation

评论

全部评论