Spring Boot + RestController 参数验证失效问题求助
Spring Boot 3.0.5 请求验证失效问题解决
问题现状
基于Spring Boot 3.0.5的RestController项目中,请求数据验证完全不生效:无论发送不符合规则的请求数据,接口始终返回201 Created。尝试过在Controller类添加@Validated、移除方法内的try-catch块等操作,问题依旧。
现有POM依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.5</version> <relativePath/> </parent> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.1.0.Final</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>${javax.validation.version}</version> </dependency>
Controller代码
@Slf4j @RestController //@Validated placing this annotation here didn't helped either public class MyController { @Autowired MyService myService; private final Counter requestCounter; public MyController(MeterRegistry meterRegistry) { this.requestCounter = meterRegistry.counter("my.counter"); } @PostMapping("/somepath") public ResponseEntity<String> handle(@RequestBody @Valid InputMessage im) { log.debug("Received message {}",im); requestCounter.increment(); try { myService.handleDoc(im); return new ResponseEntity<>("Done", HttpStatus.CREATED); }catch (Exception ex){ log.error("Error with document with message id {}",im.getId(), ex); return new ResponseEntity<>("Failed to process request", HttpStatus.BAD_REQUEST); } } }
InputMessage实体类
import javax.validation.constraints.*; @Data public class InputMessage { @Size(min = 1, max = 10) public String id; @NotBlank @Email public String email; @NotBlank //the same with @NotNull here public Integer status; @NotBlank public String error; }
问题根源与解决方案
1. 清理依赖冲突(核心修复)
Spring Boot 3.x 基于Jakarta EE规范,你的依赖存在三大问题:混合新旧API包、重复依赖、验证器版本过低,直接导致验证功能失效。
修改POM,仅保留必要依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.5</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Boot 验证启动器,自动引入适配版本的Jakarta验证API和Hibernate Validator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!-- 移除所有javax.validation、手动引入的jakarta.validation-api、旧版本hibernate-validator --> </dependencies>
spring-boot-starter-validation已包含适配Spring Boot 3.x的验证API和实现,无需手动引入。- 旧的
javax.validation包与Spring Boot 3.x完全不兼容,必须删除。 - 删除重复的
spring-boot-starter-validation依赖。
2. 修正实体类注解包与规则
Spring Boot 3.x 必须使用jakarta.validation.constraints包下的验证注解,同时注意注解的适用类型:
import jakarta.validation.constraints.*; // 替换javax为jakarta @Data public class InputMessage { @Size(min = 1, max = 10) public String id; @NotBlank @Email public String email; @NotNull // Integer类型不能用@NotBlank,@NotBlank仅适用于字符串 public Integer status; @NotBlank public String error; }
@NotBlank仅对字符串有效,Integer类型需用@NotNull。
3. 处理验证异常捕获
验证失败时,Spring会在进入Controller方法体之前抛出MethodArgumentNotValidException,不会走到你写的try-catch块中。可以添加全局异常处理器自定义响应:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<String> handleValidationExceptions(MethodArgumentNotValidException ex) { StringBuilder sb = new StringBuilder(); ex.getBindingResult().getAllErrors().forEach(error -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); sb.append(fieldName).append(": ").append(errorMessage).append("; "); }); return new ResponseEntity<>(sb.toString(), HttpStatus.BAD_REQUEST); } }
若不需要自定义响应,也可移除Controller内的try-catch块,让Spring返回默认验证错误响应。
4. 确认Controller注解正确性
@RequestBody参数上添加@Valid是正确用法,无需在Controller类上添加@Validated(除非需要路径变量等参数级验证),确保@Valid是jakarta.validation.Valid包下的注解。
内容的提问来源于stack exchange,提问作者Victoria Agafonova
相关产品推荐
相关产品推荐

