Spring Validation 让参数校验更优雅!

我们一般都需要对接口参数进行校验,但一般都会觉得 if-else 的方式不够优雅,不妨试试 Spring Validation。

本文将介绍 Spring Validation 的使用方法、常用注解、自定义校验规则,以及在实际项目中的最佳实践。


一、什么是 Spring Validation?

Spring Validation 是 Spring 框架对 JSR-303/JSR-380(Bean Validation)规范 的实现,用于对 Java Bean 的属性进行声明式校验。它通过注解的方式,将校验逻辑与业务代码解耦,让代码更清晰、更易维护。

JSR-303:Bean Validation 1.0
JSR-380:Bean Validation 2.0(支持 Java 8+,如 Optional、LocalDateTime 等)

Spring Boot 默认集成了 Hibernate Validator(Bean Validation 的参考实现),一般只需引入 spring-boot-starter-web,它已经默认包含了 hibernate-validator:

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

如果你使用的是非 Spring Boot 项目,需要手动添加:

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


二、快速上手:一个简单例子

1. 定义请求对象

public class UserRequest {
    @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 省略
}

2. 在 Controller 中启用校验

@RestController
public class UserController {

    @PostMapping("/user")
    public ResponseEntity<String> createUser(
        @Valid @RequestBody UserRequest request) {
        // 如果校验失败,会自动抛出 MethodArgumentNotValidException
        return ResponseEntity.ok("用户创建成功");
    }
}

⚠️ 注意:必须加上 @Valid 或 @Validated 注解,才能触发校验!

3. 全局异常处理(推荐)

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(
            MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            errors.put(error.getField(), error.getDefaultMessage())
        );
        return ResponseEntity.badRequest().body(errors);
    }
}

这样,当参数校验失败时,前端会收到清晰的错误信息,例如:

{
  "username": "用户名不能为空",
  "email": "邮箱格式不正确"
}

三、常用校验注解一览

注解

说明

@NotNull

不能为 null(但可以是空字符串)

@NotEmpty

不能为 null 且长度 > 0(适用于 String、Collection 等)

@NotBlank

不能为 null 且去除空格后长度 > 0(仅用于 String)

@Email

邮箱格式校验

@Pattern(regexp = “…”)

正则表达式校验

@Min / @Max

数值范围校验

@Size(min=, max=)

字符串/集合长度校验

@Past / @Future

时间必须在过去/未来

@AssertTrue

布尔值必须为 true(常用于同意协议等)


四、分组校验:不同场景不同规则

有时同一个对象在不同接口中校验规则不同。列如注册时需要邮箱,修改资料时可选。

1. 定义分组接口

public interface CreateGroup {}
public interface UpdateGroup {}

2. 在字段上指定分组

public class UserRequest {
    @NotBlank(groups = CreateGroup.class)
    private String username;

    @Email(groups = {CreateGroup.class, UpdateGroup.class})
    private String email;
}

3. Controller 中指定使用哪个分组

@PostMapping("/user")
public String createUser(@Validated(CreateGroup.class) @RequestBody UserRequest req) {
    // 只校验 CreateGroup 相关的字段
}

五、自定义校验:灵活应对业务需求

当内置注解无法满足需求时,我们可以自定义校验逻辑。

示例:校验手机号格式

1. 定义注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface ValidPhone {
    String message() default "手机号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

2. 实现校验逻辑

public class PhoneValidator implements ConstraintValidator<ValidPhone, String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) return true; // null 由 @NotNull 处理
        return value.matches("^1[3-9]d{9}$");
    }
}

3. 使用

public class UserRequest {
    @ValidPhone
    private String phone;
}

六、最佳实践提议

  1. 不要在 Controller 层写 if-else 校验,统一使用 Validation。
  2. 结合全局异常处理,返回结构化错误信息。
  3. 合理使用分组校验,避免重复定义 DTO。
  4. 自定义校验器要轻量,避免复杂业务逻辑。
  5. 前端也应做基础校验,但后端校验不可省略(安全兜底)。

七、结语

Spring Validation 让参数校验变得简单、统一、可维护。掌握它,不仅能提升开发效率,还能让你的 API 更健壮、更专业。

小贴士:如果你的项目还在用大量 if 判断做参数校验,是时候重构了!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 共1条

请登录后发表评论