Spring是否可在Controller参数转换前执行校验而非转换后校验?
可直接落地的两种实现方式
方式一:调整Controller入参(最优方案,无额外配置)
直接修改Controller方法的入参类型为DogRestDto,搭配@Valid/@Validated注解触发JSR校验,校验通过后再手动转换为Dog对象处理业务逻辑即可,示例:
@RestController @RequestMapping("/dog") public class DogController { private final DogConverter dogConverter; // 业务service省略 public DogController(DogConverter dogConverter) { this.dogConverter = dogConverter; } @PostMapping public void save(@RequestBody @Valid DogRestDto dto) { Dog dog = dogConverter.convert(dto); // 后续业务处理 } }
这种方式下校验完全针对客户端传入的DTO,错误信息里的字段名自然就是legs,完全匹配客户端的传参字段,不需要额外定制错误信息。
方式二:转换器内前置校验(适配不能修改Controller入参的场景)
如果因为架构约束必须保留Controller入参为Dog类型,则可以在自定义转换器中注入Validator实例,转换DogRestDto前先执行校验,不通过直接抛出异常:
@Component public class DogRestDtoToDogConverter implements Converter<DogRestDto, Dog> { private final Validator validator; // Spring Boot环境下Validator已经自动配置,直接注入即可 public DogRestDtoToDogConverter(Validator validator) { this.validator = validator; } @Override public Dog convert(DogRestDto source) { // 前置校验DTO Set<ConstraintViolation<DogRestDto>> violations = validator.validate(source); if (!violations.isEmpty()) { throw new ConstraintViolationException(violations); } // 正常转换逻辑 Dog dog = new Dog(); dog.setNumberOfLegs(source.getLegs()); return dog; } }
Spring MVC的全局异常处理器会自动识别ConstraintViolationException,提取其中的字段信息拼接错误响应,返回的字段名就是DTO中定义的legs。
内容的提问来源于stack exchange,提问作者whistling_marmot
相关产品推荐
相关产品推荐

