为什么需要接口参数校验?
在前后端分离、微服务架构下,接口请求往往来自不可信的客户端或第三方系统,因此必须对输入进行严格验证:
❗常见问题包括:
问题  | 描述  | 
空值提交  | 导致 NPE 异常  | 
非法格式  | 如手机号、邮箱格式错误  | 
越界数据  | 如年龄为负数、价格为负等  | 
安全loudong  | SQL zhuru、XSS gongji等  | 
使用 @Valid 可以帮助我们在进入业务逻辑之前就拦截这些非法请求,提升系统健壮性。
🧱 示例目标
我们将构建一个简单的用户注册接口,并实现如下功能:
- 使用 
@Valid对请求体进行字段校验 - 自定义全局异常处理器捕获 
MethodArgumentNotValidException - 返回结构化的错误信息给前端
 - 支持多语言国际化提示(可选)
 
⚙️ 开发环境要求
工具  | 版本建议  | 
JDK  | Java 8 / 11 / 17  | 
IDE  | IntelliJ IDEA / VS Code  | 
构建工具  | Maven  | 
Spring Boot  | 2.6.x / 2.7.x / 3.x  | 
🛠️ 步骤一:添加依赖(Maven)
<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Validation Starter(已包含在 web starter 中,可省略) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
</dependencies>💡 注意:如果你使用的是 spring-boot-starter-web,则 validation 是默认引入的,无需额外添加。
🧪 步骤二:创建请求 DTO 类
package com.example.demo.dto;
import jakarta.validation.constraints.*;
public class RegisterRequest {
    @NotBlank(message = "用户名不能为空")
    private String username;
    @Email(message = "邮箱格式不正确")
    private String email;
    @Size(min = 6, max = 20, message = "密码长度应在 6 到 20 个字符之间")
    private String password;
    @Min(value = 18, message = "年龄必须大于等于 18 岁")
    private int age;
    // Getter & Setter
}▶️ 步骤三:编写 Controller 接口并启用校验
@RestController
@RequestMapping("/api/auth")
public class AuthController {
    @PostMapping("/register")
    public ResponseEntity<String> register(@Valid @RequestBody RegisterRequest request) {
        return ResponseEntity.ok("注册成功!");
    }
}🧨 步骤四:统一异常处理(Global Exception Handler)
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
}📊 测试请求示例
请求体:
{
  "username": "",
  "email": "not-an-email",
  "password": "123",
  "age": 16
}返回结果:
{
  "username": "用户名不能为空",
  "email": "邮箱格式不正确",
  "password": "密码长度应在 6 到 20 个字符之间",
  "age": "年龄必须大于等于 18 岁"
}









