Spring REST API中List<DTO>直接校验失效原因及无封装类方案
Spring MVC直接校验List失效的原因与解决办法
问题场景
在REST API的PUT请求中,需要接收DTO列表,DTO的value字段通过@Pattern(regexp = "[^~]+")校验禁止包含~字符。使用封装了List的ListOfDtos类作为请求体参数时,校验功能正常;但直接使用@RequestBody List<@Valid DTO>作为参数时,DTO的校验规则完全失效。
失效原因
Spring MVC的Bean Validation机制默认仅对顶层JavaBean对象触发校验逻辑:
- 当使用
ListOfDtos封装类时,它是标准的自定义JavaBean,@Valid注解会触发对其内部dtos属性的校验,再结合属性上的@Valid和泛型中的@Valid,就能递归校验列表中的每个DTO实例。 - 直接使用
List作为顶层参数时,List属于Java集合框架类,并非自定义JavaBean,不符合Spring Bean Validation对顶层校验对象的要求,因此@Valid无法触发对列表内部DTO元素的递归校验。
无需封装类的解决办法
方法1:使用@Validated注解开启方法级校验
在控制器类上添加@Validated注解,同时在List参数上保留@Valid,借助Spring的Method Validation机制触发列表元素的校验:
@RestController @RequestMapping("/api") @RequiredArgsConstructor @Validated // 开启方法级校验 public class RestController { private final RestService restService; @PutMapping public void update(@RequestBody @Valid List<DTO> dtos) { restService.update(dtos); } }
注意:需确保项目已引入
spring-boot-starter-validation依赖(或手动引入javax.validation:validation-api与org.hibernate.validator:hibernate-validator)。
方法2:自定义List类型的校验器(可选)
如果需要定制化校验逻辑,可以实现Validator接口自定义针对List<DTO>的校验器,然后将其注册到Spring容器中。不过这种方式复杂度较高,仅在特殊场景下使用,一般优先推荐方法1。
内容的提问来源于stack exchange,提问作者Martin Kršek
相关产品推荐
相关产品推荐

