Java Spring Boot中如何通用校验REST接口入参的字段合法取值?
固定取值字段通用校验方案
完全不需要为每个字段单独编写校验逻辑,基于Bean Validation规范实现一套通用约束注解,就能覆盖所有固定取值范围的字段校验,不管字段是字符串、整数还是其他基础类型都能兼容,单字段配置成本只有一行注解,500个字段的场景10分钟就能配置完。
核心实现
1. 定义通用校验注解
这个注解支持在任意字段上使用,只需要传入该字段允许的取值列表即可:
import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = AllowedValueValidator.class) @Documented public @interface AllowedValues { String[] value(); // 字段允许的取值列表 String message() default "传入值不在允许范围内"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
2. 实现通用校验逻辑
校验器自动适配所有基础类型,传入值不在允许列表时直接返回校验不通过,触发异常:
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class AllowedValueValidator implements ConstraintValidator<AllowedValues, Object> { private Set<String> allowedValueSet; @Override public void initialize(AllowedValues constraintAnnotation) { allowedValueSet = new HashSet<>(Arrays.asList(constraintAnnotation.value())); } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { // 空值放行,非空校验搭配@NotNull注解实现,避免和其他校验规则冲突 if (value == null) { return true; } // 统一转字符串比对,兼容String、int、long等所有基础类型 return allowedValueSet.contains(value.toString()); } }
配置生效规则
- 引入Spring校验依赖:如果是SpringBoot项目直接引入
spring-boot-starter-validation即可,不需要额外做版本配置。 - 触发校验:在Controller层的JSON入参前添加
@Valid注解,示例:public Result saveCustomer(@Valid @RequestBody Customer customer),不加这个注解Bean Validation不会执行,这也是之前你用枚举校验方案不抛异常的最常见原因。 - 全局异常处理:新增全局异常拦截器,捕获
MethodArgumentNotValidException和ConstraintViolationException两类校验异常,直接把校验失败的信息返回给前端,校验不通过时不会进入业务逻辑,直接返回错误。
实体类使用示例
你的Customer类只需要给对应字段加上注解,不需要写任何额外校验方法:
public class Customer { private long id; @AllowedValues(value = {"MALE", "FEMALE"}, message = "性别仅支持传入MALE/FEMALE") private String gender; @AllowedValues(value = {"0", "1"}, message = "validated字段仅支持传入0/1") private int validated; @AllowedValues(value = {"PLAN1", "PLAN2", "PLAN3", "PLAN4"}, message = "plan字段取值非法") private String plan; }
如果你的固定取值本身维护在枚举类里,只需要调整注解的参数传入逻辑,自动读取枚举类的所有实例值作为允许列表即可,不需要在注解里硬编码取值字符串,核心校验逻辑不需要改动。
之前枚举校验不抛异常的常见排查点
- 入参前未加
@Valid/@Validated注解,校验逻辑根本没触发 - 自定义校验器的
isValid方法逻辑有误,永远返回true - 未配置全局异常拦截,校验抛出的异常被容器默认处理,没有按预期暴露
内容的提问来源于stack exchange,提问作者udaykiran ch
相关产品推荐
相关产品推荐

