spring-boot-starter-validation字段数据校验

validation

概述

spring-boot-starter-validation 是 Spring Boot 官方提供的用于数据校验的启动器,它基于 Bean Validation API (JSR 380) 标准,并默认使用 Hibernate Validator 作为其实现。这个框架能让你通过声明式的注解,轻松地对控制器接收的参数、服务层的方法参数以及任何 Java Bean 进行校验,确保数据的完整性和有效性。

添加依赖

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

常用注解

注解 适用类型 说明 示例
基础校验
@NotNull 任意类型 校验字段值不能为 null @NotNull(message = "ID不能为空")
@NotEmpty String/Collection/Array/Map 校验对象不能为 null 且长度/大小必须大于 0 @NotEmpty(message = "列表不能为空")
@NotBlank String 校验字符串不能为 null 且去首尾空格后长度大于 0 @NotBlank(message = "名称不能为空")
@Null 任意类型 (新增) 校验字段值必须为 null @Null(message = "创建时ID必须为空")
@Size String/Collection/Array/Map 校验长度或大小是否在指定范围内 @Size(min=6, max=20, message="长度需在6-20之间")
数值校验
@Min / @Max 数值类型 校验数值是否大于等于/小于等于指定值 @Min(value=18, message="年龄需大于18")
@DecimalMin / @DecimalMax (新增) BigDecimal/String/数值 类似于 Min/Max,但支持字符串值,适用于高精度数值(如金额) @DecimalMin(value="0.01", message="金额不能小于0.01")
@Digits (新增) BigDecimal/数值/String 校验数值必须符合指定的整数位和小数位长度 @Digits(integer=5, fraction=2, message="金额格式错误")
@Positive (新增) 数值类型 校验数值必须为正数(> 0) @Positive(message = "数量必须为正数")
@PositiveOrZero (新增) 数值类型 校验数值必须为正数或 0(>= 0) @PositiveOrZero(message = "数量不能为负")
@Negative (新增) 数值类型 校验数值必须为负数(< 0) @Negative(message = "数值必须为负")
@NegativeOrZero (新增) 数值类型 校验数值必须为负数或 0(<= 0) @NegativeOrZero(message = "数值不能为正")
逻辑校验
@AssertTrue (新增) Boolean 校验字段值必须为 true @AssertTrue(message = "必须同意协议")
@AssertFalse (新增) Boolean 校验字段值必须为 false @AssertFalse(message = "逻辑状态必须为假")
日期校验
@Future / @Past 日期时间类型 校验日期是否在未来/过去 @Future(message = "活动日期必须是未来")
@FutureOrPresent (新增) 日期时间类型 校验日期是否在未来或当前时刻 @FutureOrPresent(message = "日期不能早于现在")
@PastOrPresent (新增) 日期时间类型 校验日期是否在过去或当前时刻 @PastOrPresent(message = "出生日期不能在未来")
格式校验
@Email String 校验是否为有效的邮箱格式 @Email(message = "邮箱格式不正确")
@Pattern String 校验字符串是否符合指定的正则表达式 @Pattern(regexp="^1[3-9]\\d{9}$", message="手机号格式错误")

自定义注解

定义注解

java 复制代码
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class) // 指定校验器
public @interface Phone {
    String message() default "手机号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

实现校验逻辑

java 复制代码
public class PhoneValidator implements ConstraintValidator<Phone, String> {
    private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.matches(PHONE_REGEX);
    }
}

使用自定义注解

java 复制代码
public class UserDTO {
    @Phone
    private String phoneNumber;
}

实战开发步骤

在DTO中定义校验规则

将校验注解直接添加到数据传输对象(DTO)的字段上,并可以通过 message 属性自定义错误信息。

java 复制代码
public class UserCreateRequest {
    @NotBlank(message = "用户名不能为空")
    @Size(max = 50, message = "用户名长度不能超过50")
    private String name;

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

    @Min(value = 18, message = "年龄必须大于等于18")
    private Integer age;
    // getters and setters...
}

在Controller层触发校验

在控制器方法的参数前使用 @Valid@Validated 注解,即可触发对该参数的校验。

java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@RequestBody @Valid UserCreateRequest request) {
        // 如果校验通过,代码会执行到这里
        return ResponseEntity.ok("用户创建成功");
    }
}
@Valid@Validated 的区别
特性 @Valid (JSR-303/349 标准) @Validated (Spring 扩展)
分组校验 不支持 支持
方法级校验 不支持 支持 (需配合 @Validated 在类上)
嵌套对象校验 支持 (需在字段上使用) 支持 (需在字段上使用)

统一处理校验异常

校验失败会抛出 MethodArgumentNotValidException 异常。通常使用 @RestControllerAdvice 进行全局统一处理,向客户端返回结构化的错误信息。

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationException(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        // 收集所有字段错误信息
        ex.getBindingResult().getFieldErrors().forEach(err ->
            errors.put(err.getField(), err.getDefaultMessage())
        );
        return ResponseEntity.badRequest().body(errors);
    }
}

分组校验

分组校验允许你在不同场景下应用不同的校验规则,例如创建(Create)和更新(Update)操作。

定义分组接口

java 复制代码
public class UserGroups {
    public interface Create {}
    public interface Update {}
}

在DTO中指定分组

java 复制代码
public class UserDTO {
    // 创建时ID必须为null,更新时ID不能为null
    @Null(groups = UserGroups.Create.class)
    @NotNull(groups = UserGroups.Update.class)
    private Long id;

    @NotBlank(groups = {UserGroups.Create.class, UserGroups.Update.class})
    private String username;
    // getters and setters...
}

在Controller中使用指定分组

java 复制代码
@PostMapping("/create")
public String create(@RequestBody @Validated(UserGroups.Create.class) UserDTO user) { ... }

@PutMapping("/update")
public String update(@RequestBody @Validated(UserGroups.Update.class) UserDTO user) { ... }
相关推荐
Dicky-_-zhang2 小时前
系统容量规划与压测实战:从1万到100万QPS的科学扩容
java·jvm
Dicky-_-zhang8 小时前
消息队列Kafka/RocketMQ选型与高可用架构:从单体到100万TPS的演进
java·jvm
晨曦中的暮雨8 小时前
4.15腾讯 CSIG云服务产线 一面
java·开发语言
fake_ss1988 小时前
AI时代学习全栈项目开发的新范式
java·人工智能·学习·架构·个人开发·学习方法
茉莉玫瑰花茶8 小时前
工作流的常见模式 [ 1 ]
java·服务器·前端
未若君雅裁8 小时前
Spring AOP、日志切面与声明式事务原理
java·后端·spring
No8g攻城狮9 小时前
【人大金仓】wsl2+ubuntu22.04安装人大金仓数据库V9
java·数据库·spring boot·非关系型数据库
xiaoerbuyu12339 小时前
开源Java 邮箱 基于SpringBoot+Vue前后端分离的电子邮件
java·开发语言
C+++Python10 小时前
C++ 进阶学习完整指南
java·c++·学习