如何创建带指定取值列表校验注解的Spring搜索DTO
实现方案
完全可以通过注解实现字段取值范围限制,以下是两种常用实现方式:
方案1:使用现成的@Pattern注解(快速实现,适合单次使用)
直接在type字段上添加正则校验注解即可:
@Getter @Setter public class SearchParams { private String title; @NotNull @Pattern(regexp = "^(approved|new|closed)$", message = "type仅允许取值为'approved'、'new'、'closed'") private String type; }
这种方案不需要额外编写代码,但如果多个字段需要复用相同的校验规则,会出现大量重复的正则表达式,维护成本较高。
方案2:自定义校验注解(推荐,复用性强)
总共需要3步完成实现:
- 定义自定义校验注解
import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = AllowedValueValidator.class) public @interface AllowedValue { // 校验失败提示信息 String message() default "取值不在允许的范围内"; // 校验分组 Class<?>[] groups() default {}; // 负载配置 Class<? extends Payload>[] payload() default {}; // 配置允许的取值列表 String[] values(); }
- 实现校验逻辑类
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.Arrays; import java.util.List; public class AllowedValueValidator implements ConstraintValidator<AllowedValue, String> { private List<String> allowedValueList; // 初始化时读取注解配置的允许值 @Override public void initialize(AllowedValue constraintAnnotation) { allowedValueList = Arrays.asList(constraintAnnotation.values()); } // 执行校验逻辑 @Override public boolean isValid(String value, ConstraintValidatorContext context) { // 空值校验可以交给@NotNull处理,这里直接返回true即可,若要求空值不通过可调整逻辑 if (value == null) { return true; } return allowedValueList.contains(value); } }
- 在DTO中使用自定义注解
@Getter @Setter public class SearchParams { private String title; @NotNull @AllowedValue(values = {"approved", "new", "closed"}, message = "type仅允许取值为'approved'、'new'、'closed'") private String type; }
注意事项
- 确保项目已经引入Bean Validation相关依赖,Spring Boot项目可以直接引入
spring-boot-starter-validation启动器 - 触发校验需要在Controller接口的DTO参数前添加
@Valid或者@Validated注解,否则校验规则不会生效 - 如果需要校验的字段是枚举类型,只需要调整自定义校验器的泛型和校验逻辑即可,实现思路一致
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

