Spring Boot 2.7升级后@RestController @Validated校验不生效求助
问题根因
校验失效是3个问题叠加导致的:
- 依赖版本完全不匹配:Spring Boot 2.7.x属于2.x版本线,全系列2.x版本的
spring-boot-starter-validation默认绑定javax.validation 2.x + Hibernate Validator 6.x 版本。你手动引入的jakarta.validation-api 3.0.2和hibernate-validator 7.0.4.Final是Spring Boot 3.0+才适配的Jakarta EE 9+规范,和2.x版本使用的javax.*包路径完全不兼容。Spring MVC内置的校验逻辑只会识别Spring容器自动配置的、符合javax规范的校验器,你手动引入的jakarta版本校验器根本不会被Web层调用。你写的单元测试能通过,是因为你手动实例化了jakarta包下的Validator对象,和Spring Web层使用的校验器完全是两套独立组件,不能证明Web层校验链路正常。 - 实体类校验注解格式错误:你贴的Service类代码中,
currentStatus字段上的NotNull注解漏写了@前缀,这个标记不会被JVM识别为合法的约束注解,就算依赖配置正确也不会触发校验。 - 不必要的注解增加干扰:作为请求参数接收的Service类是普通POJO,不需要加
@Component注解交给Spring容器管理,加了之后可能被Spring代理,干扰参数绑定和校验逻辑。
修复步骤
- 第一步:清理pom.xml中冗余的校验依赖,删掉你手动添加的
jakarta.validation-api、hibernate-validator两个依赖,不要手动指定校验相关包的版本,Spring Boot 2.7.0的父POM已经默认管理了适配当前版本的校验组件,只需要保留官方starter即可:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
如果一定要使用jakarta.validation 3.x + Hibernate Validator 7.x的组合,必须整体升级到Spring Boot 3.0及以上版本,同时将JDK升级到17,2.x版本线没有兼容Jakarta EE 9+的计划。
- 第二步:修正Service类代码:
- 删掉类上的
@Component注解 - 给
currentStatus字段上的NotNull注解补上@前缀 - 校验注解的导包必须是
javax.validation.constraints.NotNull,不要导入jakarta包下的同名类
修正后的核心代码如下:
- 删掉类上的
// 注意导包:import javax.validation.constraints.NotNull; public class Service { private int id; @NotNull(message = "Current status is required", groups = {OnCreate.class, OnUpdate.class}) private ServiceStatus currentStatus; }
- 第三步:调整Controller层的校验组配置:你在方法上添加了
@Validated(OnUpdate.class),但参数上使用的@Valid注解不会继承方法上定义的校验组,会导致组匹配失败。直接将@RequestBody参数上的@Valid替换为@Validated(OnUpdate.class)即可,不需要在方法上重复加@Validated注解。修正后的方法代码示例:
@RestController @RequestMapping("v1/services") @Validated public class ServiceController { @PutMapping( path = "/{id}", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE ) public ResponseEntity<Service> updateService(@PathVariable("id") int serviceId, @Validated(OnUpdate.class) @RequestBody Service service) { // 业务逻辑 } }
验证方式
修改完成后执行mvn clean compile重新编译启动,发送currentStatus字段为null的PUT请求到对应接口,就会正常触发参数校验,抛出MethodArgumentNotValidException,如果需要自定义校验失败的返回格式,全局捕获该异常统一处理即可。
内容的提问来源于stack exchange,提问作者Ashley-Richard Walker
相关产品推荐
相关产品推荐

