Spring Boot中带参构造的@Constraint校验器与Togglz集成疑问
问题:Spring Boot校验器集成Togglz的构造方法问题
我有一个Spring Boot应用,其中一个接口带有校验约束:
@Constraint( validatedBy = { MyValidator.class }) public @interface MyInterface { ... }
我正在使用Togglz来启用/禁用部分功能,希望在MyValidator中实现相关Togglz代码:
public class MyValidator implements ConstraintValidator<MyInterface, TDLDetails> { // 注:原代码此处接口实现错误,已修正为标准ConstraintValidator private FeatureManager featureManager; public static final Feature FEATURE_ONE = new NamedFeature("FEATURE_ONE"); // 注:原代码名称末尾带空格,已修正 public MyValidator(FeatureManager featureManager) { this.featureManager = featureManager; } @Override public void initialize(MyInterface arg0) {} @Override public boolean isValid(TDLDetails tdlDetails, ConstraintValidatorContext ctx) { if (!featureManager.isActive(FEATURE_ONE)) { if (tdlDetails.getType().equals(TDLType.ANA)) { return (tdlDetails.getPlaceOfIssue() != null); } } return true; } }
我为MyValidator添加带参构造方法是否合理?我需要它来集成Togglz,但不确定@Constraint如何使用带参构造的校验器,正确的实现方式是什么?
解答
带参构造方法本身是合理的,但直接按你当前写法会导致Bean Validation默认工厂无法实例化校验器——因为默认规则要求校验器必须有无参构造方法。在Spring Boot环境下,推荐以下两种实现方式:
方法一:Spring容器托管校验器(推荐)
利用Spring的依赖注入能力,让容器接管校验器的实例化:
- 给
MyValidator添加@Component注解,纳入Spring管理:
@Component public class MyValidator implements ConstraintValidator<MyInterface, TDLDetails> { private final FeatureManager featureManager; // Spring 4.3+支持构造方法自动注入,无需@Autowired public MyValidator(FeatureManager featureManager) { this.featureManager = featureManager; } // 其余代码保持不变 }
- 修改
@Constraint注解的validatedBy属性为空白,让Spring自动关联容器中的校验器实例:
@Constraint(validatedBy = {}) public @interface MyInterface { String message() default "校验不通过"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
方法二:自定义ConstraintValidatorFactory
如果不想让校验器被Spring托管,可以自定义工厂来创建带参实例:
- 实现
ConstraintValidatorFactory,从Spring容器获取实例:
@Component public class SpringConstraintValidatorFactory implements ConstraintValidatorFactory { private final ApplicationContext applicationContext; public SpringConstraintValidatorFactory(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) { return applicationContext.getBean(key); } }
- 配置Bean Validation使用自定义工厂:
@Configuration public class ValidationConfig { @Bean public Validator validator(SpringConstraintValidatorFactory factory) { return Validation.byDefaultProvider() .configure() .constraintValidatorFactory(factory) .buildValidatorFactory() .getValidator(); } }
额外注意事项
- 原代码中
implements MyInterface<MyInterface, TDLDetails>是错误的,校验器必须实现JSR-380标准的ConstraintValidator<A, T>接口。 NamedFeature的名称不要带多余空格,否则会导致Togglz无法正确匹配功能开关。
内容的提问来源于stack exchange,提问作者runnerpaul
相关产品推荐
相关产品推荐

