Java Record封装查询参数时@NotNull校验失效问题
Java Record字段校验注解(@NotNull/@NotBlank)不生效导致NPE的解决方案
当使用Java Record封装请求查询参数时,字段上的@NotNull、@NotBlank注解未生效。缺少必填参数的请求未返回预期的400 Bad Request,而是因空指针异常(NPE)返回500错误——自定义类级校验器执行时,访问了未校验的null字段。
场景示例:
- 有效请求:
http://localhost:8080/api/client?searchKey=NAME&value=John - 无效请求(应返回400但返回500):
http://localhost:8080/api/client?searchKey=NAME(缺少value参数)http://localhost:8080/api/client?value=John(缺少searchKey参数)
1. 确保引入Bean Validation依赖
Spring Boot项目需引入spring-boot-starter-validation,提供Hibernate Validator等校验实现:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
2. 调整类级校验的执行顺序
自定义类级注解会优先于字段级注解执行,导致字段未校验就进入校验器引发NPE。通过@GroupSequence指定校验顺序,让字段级校验(默认组)先执行:
修改@ValidPersonSearchParameter注解:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = PersonSearchParameterValidator.class) @GroupSequence({Default.class, ValidPersonSearchParameter.class}) public @interface ValidPersonSearchParameter { String message() default "Invalid search parameter"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
3. 确保Record字段注解被正确识别
Hibernate Validator 6.1+已原生支持Java Record的组件注解,无需额外修改Record。若使用旧版本,需显式在构造方法参数上添加校验注解:
// 旧版本兼容写法(可选) public record PersonSearchParameters( @NotNull SearchKey searchKey, @NotBlank String value ) { public PersonSearchParameters(@NotNull SearchKey searchKey, @NotBlank String value) { this.searchKey = searchKey; this.value = value; } }
4. 控制器校验配置保持正确
控制器类上的@Validated启用Spring校验,方法参数上的@Valid触发Record的字段校验:
@RestController @RequestMapping(value = "/api/client", produces = APPLICATION_JSON_VALUE) @RequiredArgsConstructor @Validated public class PersonController { @GetMapping public PersonInfoResponse getPersonInfo(@Valid @NotNull PersonSearchParameters parameters) { // 业务逻辑 } }
5. 优化自定义校验器逻辑
字段级校验通过后,自定义校验器无需再处理null值,可直接执行业务校验:
public class PersonSearchParameterValidator implements ConstraintValidator<ValidPersonSearchParameter, PersonSearchParameters> { @Override public boolean isValid(PersonSearchParameters parameters, ConstraintValidatorContext context) { // 此时searchKey和value已通过@NotNull/@NotBlank校验,无需判空 // 执行自定义校验逻辑,例如:检查searchKey与value的匹配规则 return true; // 根据实际业务返回校验结果 } }
原理说明
- 未调整校验顺序时,类级校验器先执行,此时字段未经过@NotNull/@NotBlank校验,访问null字段直接抛出NPE。
- 通过
@GroupSequence指定顺序后,字段级校验(默认组)优先执行,若参数缺失,直接返回400 Bad Request,不会进入自定义校验器。 - 确保依赖正确是Bean Validation生效的基础,Spring Boot starter已整合所需的校验组件。
内容的提问来源于stack exchange,提问作者stakeika
相关产品推荐
相关产品推荐

