Spring Boot泛型类中Jakarta Validation验证失效问题排查
泛型父类中Jakarta Validation失效的原因与解决办法
核心问题出在Java泛型的类型擦除:编译后泛型父类的T会被擦除为Object,Spring MVC无法通过反射识别到实际传入的CarDTO类型,自然也就读取不到字段上的@NotBlank等校验注解,导致@Valid注解完全没触发校验逻辑。这也是你测试非泛型方法正常、泛型方法失效的根本原因。
下面给几种不用重写父类方法(避免重复端点)的解决办法:
办法1:子类添加@Validated并指定校验类型
直接在CarServices类上加上@Validated,并明确指定要校验的CarDTO类型,让Spring能定位到具体的校验元数据:
@RestController @Validated(CarDTO.class) @RequestMapping("/cars") public class CarServices extends BasicServices<CarDTO> { // 不用重写父类的add方法 }
父类的add方法保持原有@Valid注解即可:
public abstract class BasicServices<T> { @PostMapping public ResponseEntity<?> add(@Valid @RequestBody T dto) { // 你的业务逻辑 return ResponseEntity.status(HttpStatus.CREATED).build(); } }
办法2:父类通过构造注入DTO的Class对象
在父类中新增构造方法,让子类传入实际DTO的Class实例,配合@Validated让Spring明确校验类型:
public abstract class BasicServices<T> { private final Class<T> dtoClass; protected BasicServices(Class<T> dtoClass) { this.dtoClass = dtoClass; } @PostMapping @Validated public ResponseEntity<?> add(@Valid @RequestBody T dto) { // 你的业务逻辑 return ResponseEntity.status(HttpStatus.CREATED).build(); } }
子类初始化时传入CarDTO.class:
@RestController @RequestMapping("/cars") public class CarServices extends BasicServices<CarDTO> { public CarServices() { super(CarDTO.class); } }
为什么非泛型方法正常?
非泛型的addNew方法参数是明确的CarDTO类型,Spring能直接读取到字段上的校验注解,所以校验逻辑正常触发。而泛型父类的方法因为类型擦除丢失了实际类型信息,导致@Valid无法发挥作用。
内容的提问来源于stack exchange,提问作者King Midas
相关产品推荐
相关产品推荐

