参数校验:@Valid 与分组校验

结论先行:Spring Boot 参数校验采用 Bean Validation 规范(JSR-380):实现为 hibernate-validator,注解来自 jakarta.validation。Controller 入参上标 @Valid(或 @Validated)触发校验,失败抛 MethodArgumentNotValidException(@RequestBody 场景),由全局异常处理器统一转 400 + 字段错误。核心差异一句话:@Valid 是 JSR 标准注解、负责触发与级联校验;@Validated 是 Spring 的,额外支持分组(groups)与类/方法级校验。分组校验 = @Validated(某组.class) 只校验该组注解。

一、@Valid vs @Validated

对比项@Valid@Validated
来源jakarta.validation(JSR-380)Spring(org.springframework.validation.annotation)
分组校验不支持(固定 Default 组)支持,groups 指定激活组
级联(内嵌对象)支持(对象字段上标 @Valid)支持
方法参数/返回值校验需配合 Spring 机制类上标注即启用
Controller 入参触发可以可以(更推荐,语义统一)

二、代码示例(分组校验)

public class UserDTO {
    public interface Create { }          // 组 1:新增
    public interface Update { }          // 组 2:修改

    @NotBlank(groups = Create.class, message = "姓名必填")   // 仅新增时校验
    private String name;

    @NotNull(groups = Update.class)      // 仅修改时校验
    private Long id;

    @Min(value = 1, groups = {Create.class, Update.class})
    private Integer age;

    @Pattern(regexp = "^1\\d{10}$", message = "手机号格式不正确")
    private String phone;                // 未指定 groups → 属于 Default 组
}

@PostMapping("/users")                                    // 只校验 Create 组
public Result<Void> create(@Validated(Create.class) @RequestBody UserDTO dto) { ... }

@PutMapping("/users/{id}")                                // 只校验 Update 组
public Result<Void> update(@Validated(Update.class) @RequestBody UserDTO dto) { ... }

三、常用校验注解速记

注解作用
@NotNull值非 null
@NotBlank / @NotEmpty字符串非空白 / 集合字符串非空
@Size(min,max)长度/大小范围
@Min / @Max / @DecimalMin / @Positive数值范围
@Pattern正则
@Email邮箱格式
@Valid(级联)校验内嵌对象

常见追问 / 记忆点

  • 追问 1:校验失败的异常类型?答:@RequestBody 校验失败抛 MethodArgumentNotValidException;@RequestParam/@PathVariable 等单参数校验失败抛 ConstraintViolationException(需在全局异常里分别处理)。
  • 追问 2:不指定组时校验哪些?答:默认 Default 组——即未声明 groups 的注解。
  • 追问 3:Service 层方法参数也能校验吗?答:能,@Validated 标在类上 + 参数/返回值加约束注解即可(Spring 方法级校验)。
  • 记忆点:"@Valid 只管触发与级联、@Validated 才管分组;校验注解标字段,groups 按场景分组激活"。
笔记加载中…