Spring Boot 参数校验:@Valid 与 @Validated

在日常开发中,参数校验 是保障接口健壮性与数据安全的第一道防线。Spring Boot 为我们提供了基于 JSR-303/JSR-380 的强大校验机制,通过注解与 AOP 实现了灵活且高效的数据校验方式。本篇博客将详细介绍 Spring Boot 中 @Valid、@Validated 注解的使用方法,并深入解析其背后的原理与扩展能力。


一、引入依赖

Spring Boot 项目中默认支持 javax.validation,但建议显式引入:

xml 复制代码
<!-- Hibernate Validator 是实现规范最广的一个实现 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

二、基础注解使用

在 Java Bean 上添加注解,示例:

java 复制代码
public class UserDTO {

    @NotBlank(message = "用户名不能为空")
    private String username;

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

    @Min(value = 18, message = "年龄必须 >= 18")
    @Max(value = 100, message = "年龄必须 <= 100")
    private Integer age;

    // Getter / Setter
}

三、在 Controller 中启用校验

1. 使用 @Valid(javax.validation)注解:

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

    @PostMapping("/create")
    public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO user) {
        return ResponseEntity.ok("创建成功");
    }
}

2. 使用 @Validated(Spring 提供)支持 分组校验:

java 复制代码
public class UserDTO {

    @NotBlank(message = "用户名不能为空", groups = Create.class)
    private String username;

    public interface Create {}
}
java 复制代码
@PostMapping("/create")
public ResponseEntity<String> createUser(@Validated(UserDTO.Create.class) @RequestBody UserDTO user) {
    return ResponseEntity.ok("按分组校验通过");
}

四、校验嵌套对象

java 复制代码
public class OrderDTO {
    @NotNull
    @Valid // 注意:嵌套对象必须加 @Valid 才能触发其内部校验
    private UserDTO user;
}

五、处理校验失败异常

Spring Boot 默认抛出 MethodArgumentNotValidException(@Valid)或 ConstraintViolationException(@Validated)。

可以通过全局异常处理捕获并格式化返回:

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> handleValidException(MethodArgumentNotValidException ex) {
        String errorMsg = ex.getBindingResult().getAllErrors()
                            .stream()
                            .map(DefaultMessageSourceResolvable::getDefaultMessage)
                            .collect(Collectors.joining("; "));
        return ResponseEntity.badRequest().body("参数错误:" + errorMsg);
    }
}

六、自定义校验注解

1. 自定义注解:

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 {};
}

2. 编写校验器:

java 复制代码
public class PhoneValidator implements ConstraintValidator<Phone, String> {

    private static final Pattern PATTERN = Pattern.compile("^1[3-9]\\d{9}$");

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

3. 使用:

java 复制代码
@Phone
private String phone;

七、常用校验注解速查表

注解 功能说明
@NotNull 不能为 null
@NotEmpty 不能为 null 且长度 > 0
@NotBlank 不能为 null 且去空格后长度 > 0
@Email 邮箱格式
@Min 最小值限制
@Max 最大值限制
@Pattern 正则校验
@Size 长度范围校验
@Future 必须是未来时间
@Past 必须是过去时间

八、注意事项与最佳实践

  • 嵌套校验字段必须加 @Valid。
  • @Validated 支持分组、@Valid 不支持。
  • 实体类字段建议使用包装类型(如 Integer 而非 int),避免 null 时校验器报错。
  • 参数校验推荐配合统一响应结构,提升开发与调试体验。

相关推荐
架构技术专栏21 分钟前
Agent 工具调用:从工具声明到执行反馈
前端·人工智能·后端
vx_bisheyuange42 分钟前
基于SpringBoot的体育商品推荐系统
spring boot·毕业设计
别动我齐刘海1 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
码事漫谈1 小时前
你让AI干的活,它可能只干了十分之一——而你根本看不出来
后端
Wx-bishekaifayuan1 小时前
express皖美特色农产品网售系统53118-计算机课程设计、毕业设计
人工智能·spring boot·后端·python·课程设计·express·旅游
Wx-bishekaifayuan2 小时前
springboot汉中旅游服务平台41442-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
code2cat2 小时前
Java进阶篇之AtomicLongFieldUpdater:把累计额度留在对象字段中
java·cas·并发编程
WeiXin_DZbishe2 小时前
基于springboot城市公交实时运营与调度系统-计算机毕设 附源码【课程设计】66173
java·vue.js·spring boot·后端·python·php·课程设计
泡茶喝茶写代码2 小时前
A股量化数据工程:从 REST 接口到策略信号(第 18 篇):放量缩量异动扫描
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口