Spring Boot项目参数校验失效:同代码在其他项目可正常运行
Spring Boot 参数校验功能不生效问题解决
问题根源
你的项目依赖存在版本不兼容问题:
- 当前项目使用Spring Boot 2.6.6,该版本基于Jakarta Validation 2.0,依赖包路径为
javax.validation - 但你引入的
spring-boot-starter-validation是3.1.0版本,属于Spring Boot 3.x生态,依赖Jakarta Validation 3.0(包路径为jakarta.validation)
版本不匹配导致参数校验的自动配置无法正常加载,因此@NotNull等校验注解完全失效。
修复步骤
- 移除冲突依赖:删除pom.xml中指定了3.1.0版本的
spring-boot-starter-validation,同时移除单独的validation-api依赖(spring-boot-starter-validation已包含所需的API和实现) - 添加匹配版本的校验 starter:使用Spring Boot父项目管理的版本,添加如下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
- 重新构建项目:执行
mvn clean install,确保依赖正确更新
验证
重启项目后,用Postman发送缺少test参数的请求,此时会触发@NotNull校验,返回400 Bad Request及对应的校验错误信息。
原问题涉及代码
实体类 TestEntity
package com.example.entity; import lombok.Data; import javax.persistence.*; @Entity @Data @Table(name = "test") public class TestEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic @Column(name = "id") private Long id; @Basic @Column(name = "test") private String test; }
响应DTO TestResponse
package com.example.dto.response; import lombok.Data; import javax.validation.constraints.NotNull; @Data public class TestResponse { private Long id; @NotNull private String test; }
请求DTO TestRequest
package com.example.dto.request; import lombok.Data; import javax.validation.constraints.NotNull; @Data public class TestRequest { @NotNull private String test; }
Repository、Controller 和 Service
TestRepo
package com.example.repository; import com.example.entity.TestEntity; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @Repository public interface TestRepo extends CrudRepository<TestEntity, Long> { }
TestController
package com.example.controller; import com.example.dto.request.TestRequest; import com.example.dto.response.TestResponse; import com.example.mapper.TestMapperImpl; import com.example.service.TestService; import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController @AllArgsConstructor @RequestMapping("/test") public class TestController { private TestService testService; private TestMapperImpl testMapper; @PostMapping("/add") public ResponseEntity<TestResponse>add(@Valid @RequestBody TestRequest testRequest){ return new ResponseEntity<>(testMapper.toDto(testService.add(testMapper.fromDto(testRequest))), HttpStatus.OK); } }
TestService
package com.example.service; import com.example.entity.TestEntity; import com.example.repository.TestRepo; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; @Service @AllArgsConstructor public class TestService { private TestRepo testRepo; public TestEntity add(TestEntity entity){ return testRepo.save(entity); } }
原项目 pom.xml 配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.6</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>kursova</name> <description>Demo project for Spring Boot</description> <properties> <java.version>17</java.version> <org.mapstruct.version>1.5.3.Final</org.mapstruct.version> <org.lombok.version>1.18.26</org.lombok.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/javax.validation/validation-api --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>3.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>${org.lombok.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!--Mapper--> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>${org.mapstruct.version}</version> </dependency> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-security</artifactId>--> <!-- </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> <annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${org.lombok.version}</version> </path> <!-- This is needed when using Lombok 1.18.16 and above --> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> <!-- Mapstruct should follow the lombok path(s) --> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${org.mapstruct.version}</version> </path> <!-- Set the componentModel to 'spring' by default --> </annotationProcessorPaths> <compilerArgs> <compilerArg> -Amapstruct.defaultComponentModel=spring </compilerArg> </compilerArgs> </configuration> </plugin> </plugins> </build> </project>
内容的提问来源于stack exchange,提问作者Ivan Poltavskiy
相关产品推荐
相关产品推荐

