Spring Boot 参数验证

一、依赖配置

首先确保在 pom.xml 中添加了以下依赖:

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

这个依赖包含了 Hibernate Validator(JSR-380 规范的实现)和必要的 Spring 验证支持。

验证执行流程

  • 当请求到达Controller方法时,Spring会检查方法参数上的@Valid@Validated注解

  • 触发MethodValidationInterceptor拦截器

  • 创建Validator实例并执行验证

  • 验证器会递归检查对象及其属性上的所有约束注解

  • 如果验证失败,收集所有违反的约束

二、基本验证注解

以下是常用的验证注解:

  • @NotNull - 值不能为 null

  • @Null - 值必须为 null

  • @AssertTrue - 值必须为 true

  • @AssertFalse - 值必须为 false

  • @Min(value) - 数字必须大于等于指定值

  • @Max(value) - 数字必须小于等于指定值

  • @DecimalMin(value) - 必须大于等于指定值(字符串形式表示)

  • @DecimalMax(value) - 必须小于等于指定值(字符串形式表示)

  • @Size(min, max) - 集合/字符串/数组大小必须在范围内

  • @Digits(integer, fraction) - 数字格式检查

  • @Past - 必须是过去的日期

  • @PastOrPresent - 必须是过去或现在的日期

  • @Future - 必须是将来的日期

  • @FutureOrPresent - 必须是将来或现在的日期

  • @Pattern(regex) - 必须匹配正则表达式

  • @Email - 必须是有效的邮箱格式

  • @Valid - 级联验证,用于验证对象中的嵌套对象

三、使用示例

1. 在实体类中使用验证注解

java 复制代码
public class User {
    
    @NotNull(message = "用户ID不能为空")
    private Long id;
    
    @NotBlank(message = "用户名不能为空")
    @Size(min = 2, max = 20, message = "用户名长度必须在2-20之间")
    private String username;
    
    @Email(message = "邮箱格式不正确")
    private String email;
    
    @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$", 
             message = "密码必须至少8个字符,包含大小写字母和数字")
    private String password;
    
    @Min(value = 18, message = "年龄必须大于等于18")
    @Max(value = 100, message = "年龄必须小于等于100")
    private Integer age;
    
    @Past(message = "出生日期必须是过去的时间")
    private LocalDate birthday;
    
    // getters and setters
}

2. 在Controller中使用验证

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
        // 业务逻辑处理
        return ResponseEntity.ok("用户创建成功");
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(
            @PathVariable @Min(1) Long id,
            @RequestParam(required = false) @Size(max = 100) String name) {
        // 业务逻辑处理
        return ResponseEntity.ok(new User());
    }
}

3. 处理验证错误

当验证失败时,Spring 会抛出 MethodArgumentNotValidException。可以全局处理这些异常:

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationExceptions(
            MethodArgumentNotValidException ex) {
        
        List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
        List<ErrorDetail> errorDetails = fieldErrors.stream()
            .map(error -> new ErrorDetail(
                error.getField(),
                error.getRejectedValue(),
                error.getDefaultMessage()))
            .collect(Collectors.toList());
        
        ErrorResponse response = new ErrorResponse(
            "VALIDATION_FAILED",
            "参数验证失败",
            errorDetails);
            
        return ResponseEntity.badRequest().body(response);
    }
}

// 响应数据结构
public class ErrorResponse {
    private String code;
    private String message;
    private List<ErrorDetail> details;
    // 构造方法/getters/setters
}

public class ErrorDetail {
    private String field;
    private Object rejectedValue;
    private String message;
    // 构造方法/getters/setters
}

响应示例

当验证失败时,返回的JSON结构如下:

java 复制代码
{
  "code": "VALIDATION_FAILED",
  "message": "参数验证失败",
  "details": [
    {
      "field": "age",
      "rejectedValue": 15,
      "message": "年龄必须大于等于18"
    },
    {
      "field": "email",
      "rejectedValue": "invalid-email",
      "message": "必须是有效的邮箱格式"
    }
  ]
}
相关推荐
tian_jiangnan9 分钟前
Flink 流计算进阶:手写一套通用的 Redis/MySQL /Kafka数据源封装工具类
redis·mysql·flink
乐启国际旅行社有限公司10 分钟前
Java线程池实战:文旅系统批量任务性能优化(团期生成/数据导出)
java·开发语言·性能优化
Listen·Rain19 分钟前
用AI开发出一个AI
java·人工智能·spring boot·tomcat·intellij-idea·mybatis·visual studio
AI人工智能+电脑小能手21 分钟前
【大白话说Java面试题 第203题】【09_Zookeeper篇】第4题:ZooKeeper 的节点类型有哪些?
java·zookeeper·分布式锁·分布式协调·znode
sevenll0728 分钟前
SqlKit - 覆盖 50+ 数据库的 AI 智能体 SQL 桌面客户端
数据库·人工智能·sql·智能体
宸津-代码粉碎机30 分钟前
告别手动Jar部署!生产级无损热部署方案,彻底解决OOM与更新失效问题
java·大数据·开发语言·人工智能·python
米码收割机32 分钟前
【移动】线上购物移动端网站(源码+文档)【独一无二】
java·开发语言·前端·python·django
无敌秋1 小时前
python/c++/java上云
java·c++·python
都叫我大帅哥1 小时前
BCrypt 还是 Argon2?Spring Security 密码加密方案深度解析与实战对比
java·spring
数智化管理手记3 小时前
手工统计指标误差大、效率低?指标管理系统如何告别人工算数痛点?
大数据·运维·数据库·人工智能·云计算