Spring Boot中RequestBody DTO校验失效问题及配置咨询
咱们来一步步排查你的校验不生效问题,尤其是你用了@RepositoryRestController,这个注解确实有一些特殊的地方需要注意:
1. 先确认校验依赖是否到位
如果是Spring Boot项目(从代码风格看大概率是),Spring Boot 2.3及以后版本的spring-boot-starter-web不再默认包含校验依赖,得手动添加:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
要是传统Spring项目,需要引入校验API和具体实现(比如Hibernate Validator):
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.7.Final</version> </dependency>
(注意:如果用的是Jakarta EE版本的Spring,把javax.validation换成jakarta.validation即可)
2. 处理@RepositoryRestController的特殊性
@RepositoryRestController是Spring Data REST的注解,它的默认配置不会自动开启方法参数的校验,有两种解决思路:
方案一:换成标准@RestController
如果你的接口不需要Spring Data REST的特殊能力,直接换成@RestController,Spring MVC会自动支持@Valid校验:
@RestController // 替换原来的@RepositoryRestController @RequestMapping(value = "/download_pdf") public class PurchaseController { // 原有代码不变 }
方案二:为Spring Data REST配置校验支持
如果必须保留@RepositoryRestController,得在配置类里显式配置校验器,或者启用方法级校验:
先编写配置类:
@Configuration public class RestConfig extends RepositoryRestConfigurerAdapter { @Override public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) { // 给创建、更新操作加上校验逻辑 validatingListener.addValidator("beforeCreate", validator()); validatingListener.addValidator("beforeSave", validator()); } @Bean public Validator validator() { return new LocalValidatorFactoryBean(); } }
另外,还可以在Controller方法上加上Spring的@Validated注解(注意是org.springframework.validation.annotation.Validated),配合@Valid一起触发校验:
@Loggable @RequestMapping(value = "view_order", method = RequestMethod.POST) public ResponseEntity getPDF(@RequestBody @Valid @Validated CustomerOfferDto offer, HttpServletResponse response) { return iPurchaseService.purchase(offer, response); }
3. 加上BindingResult捕获校验错误
有时候校验其实已经触发了,但你没捕获错误,就会误以为没生效。在方法参数里加个BindingResult,就能拿到具体的校验结果了:
public ResponseEntity getPDF(@RequestBody @Valid CustomerOfferDto offer, BindingResult result, HttpServletResponse response) { // 先检查有没有校验错误 if (result.hasErrors()) { // 收集错误信息并返回 List<String> errorMessages = result.getAllErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .collect(Collectors.toList()); return ResponseEntity.badRequest().body(errorMessages); } return iPurchaseService.purchase(offer, response); }
这样如果agentCode为空,你就能看到明确的错误提示了。
4. 检查注解导入是否正确
别搞错注解的包路径:
@Valid要导入javax.validation.Valid(或Jakarta的jakarta.validation.Valid),不是Spring的org.springframework.validation.annotation.Valid@NotNull要导入javax.validation.constraints.NotNull(或Jakarta对应包)
5. 确认WebMvc自动配置没被禁用
如果你自定义了WebMvc配置(比如继承了WebMvcConfigurationSupport),会禁用默认自动配置,得手动配置校验器:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public Validator getValidator() { return new LocalValidatorFactoryBean(); } }
内容的提问来源于stack exchange,提问作者chrisblo

