Spring Boot自定义约束校验器重复注解报错,如何支持多Feature Flag?
解决重复注解编译错误的方法
出现“Duplicate annotation”编译错误的核心原因是:Java默认不允许同一注解在同一元素上重复使用,除非该注解被标记为@Repeatable,并搭配对应的容器注解。以下是具体解决步骤:
1. 创建容器注解
定义一个用来容纳多个BlockedWithoutEnabledFeatureFlag注解的容器注解,需满足JSR-380校验框架的规范要求:
@Constraint(validatedBy = {BlockedWithoutEnabledFeatureFlagsValidator.class}) @Target({FIELD, PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface BlockedWithoutEnabledFeatureFlags { // 用来存储多个重复的注解实例 BlockedWithoutEnabledFeatureFlag[] value(); // 必须包含校验注解的标准属性 String message() default "{validation.constraints.BlockedWithoutEnabledFeatureFlags.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
2. 标记原注解为可重复注解
在原BlockedWithoutEnabledFeatureFlag注解上添加@Repeatable注解,指定对应的容器注解:
@Constraint(validatedBy = {BlockedWithoutEnabledFeatureFlagValidator.class}) @Target({FIELD, PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @ReportAsSingleViolation @Repeatable(BlockedWithoutEnabledFeatureFlags.class) // 新增该行,标记为可重复注解 public @interface BlockedWithoutEnabledFeatureFlag { String message() default "{validation.constraints.BlockedWithoutEnabledFeatureFlag.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; FeatureFlag feature(); String[] values() default {}; }
3. 实现容器注解的校验器
容器注解需要对应的校验器来处理多个注解实例的逻辑,这里可以复用原单个注解的校验逻辑,避免重复代码:
public class BlockedWithoutEnabledFeatureFlagsValidator implements ConstraintValidator<BlockedWithoutEnabledFeatureFlags, Object> { private final FeatureFlagService featureFlagService; private List<BlockedWithoutEnabledFeatureFlagValidator> validators = new ArrayList<>(); // 通过构造函数注入依赖 public BlockedWithoutEnabledFeatureFlagsValidator(FeatureFlagService featureFlagService) { this.featureFlagService = featureFlagService; } @Override public void initialize(BlockedWithoutEnabledFeatureFlags constraintAnnotation) { // 初始化每个单个注解的校验器实例 for (BlockedWithoutEnabledFeatureFlag annotation : constraintAnnotation.value()) { BlockedWithoutEnabledFeatureFlagValidator validator = new BlockedWithoutEnabledFeatureFlagValidator(featureFlagService); validator.initialize(annotation); validators.add(validator); } } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { // 遍历所有校验器,只要有一个校验不通过则整体返回false for (BlockedWithoutEnabledFeatureFlagValidator validator : validators) { if (!validator.isValid(value, context)) { return false; } } return true; } }
4. 正常使用重复注解
现在可以在字段上重复添加@BlockedWithoutEnabledFeatureFlag注解,编译不会再报错:
@JsonProperty(value = "name") @BlockedWithoutEnabledFeatureFlag(feature = FeatureFlag.AAA, values = {"aaa", "bbb"}) @BlockedWithoutEnabledFeatureFlag(feature = FeatureFlag.BBB, values = {"ccc", "ddd"}) private String parameter;
内容的提问来源于stack exchange,提问作者Matexon
相关产品推荐
相关产品推荐

