Java Dropwizard 初始化 ConstraintValidator

Kou*_*sha 1 java dropwizard

假设我有一个自定义 ConstraintValidator:

public class FooValidator implements ConstraintValidator<ValidFoo, String> {
    @Override
    public void initialize(final ValidFoo foo) {
        // No-op
    }

    @Override
    public boolean isValid(final String foo, final ConstraintValidatorContext context) {

    }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够通过从ServiceConfigurationDropwizardruninitialize.

这可能吗?

Amr*_*afa 5

首先,值得注意的是即将发布的 Dropwizard 2.0.0 版本内置了对此的支持


目前,这个过程有点复杂。您基本上想要重新引导 Hibernate 验证,但使用支持注入的自定义约束验证器工厂。

它将涉及大约 4 个自定义课程,所以请耐心等待。开始:

首先,我们首先注册一个自定义功能以将此功能包装到我们的Application类中:

public void run(MainConfiguration config, Environment environment) throws Exception {
  // ...
  environment.jersey().register(InjectingValidationFeature.class);
}
Run Code Online (Sandbox Code Playgroud)

现在我们定义该功能:InjectingValidationFeature- 它基本上在服务容器中注册我们的自定义实现:

public class InjectingValidationFeature implements Feature {

  @Override
  public boolean configure(FeatureContext context) {
    context.register(new AbstractBinder() {
      @Override
      protected void configure() {
        bindFactory(ValidatorFactory.class).to(Validator.class).in(Singleton.class);
        bind(InjectingConfiguredValidator.class).to(ConfiguredValidator.class).in(Singleton.class);
        bind(InjectingConstraintValidatorFactory.class).to(ConstraintValidatorFactory.class).in(Singleton.class);
      }
    });

    return true;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我们定义上面注册的那些类。让我们从核心部分开始,InjectingConstraintValidatorFactoryHibernate Validator 将实际使用它来创建约束验证器。请注意,因为我们正在容器中注册它们,所以我们实际上已经可以开始注入东西了,这是我们ConstraintValidatorFactory使用服务定位器来使依赖项注入成为可能的自定义:

public class InjectingConstraintValidatorFactory implements ConstraintValidatorFactory {

  private final ServiceLocator serviceLocator;

  @Inject
  public InjectingConstraintValidatorFactory(ServiceLocator serviceLocator) {
    this.serviceLocator = serviceLocator;
  }

  @Override
  public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
    return this.serviceLocator.createAndInitialize(key);
  }

  @Override
  public void releaseInstance(ConstraintValidator<?, ?> instance) {
    this.serviceLocator.preDestroy(instance);
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我们的中央javax.validation.Validator接口工厂:

public class ValidatorFactory implements Factory<Validator> {

  private final ConstraintValidatorFactory constraintValidatorFactory;

  @Inject
  public ValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
    this.constraintValidatorFactory = constraintValidatorFactory;
  }

  @Override
  public Validator provide() {
    return Validation.byDefaultProvider().configure().constraintValidatorFactory(
        this.constraintValidatorFactory).buildValidatorFactory()
        .getValidator();
  }

  @Override
  public void dispose(Validator instance) {
    // Nothing
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,我们的InjectingConfiguredValidator,注意它是如何使用的DropwizardConfiguredValidator,但是使用@Inject它可以让我们从上面接收验证器ValidatorFactory

public class InjectingConfiguredValidator extends DropwizardConfiguredValidator {
  @Inject
  public InjectingConfiguredValidator(Validator validator) {
    super(validator);
  }
}
Run Code Online (Sandbox Code Playgroud)

就是这样。通过上述内容,我们成功地在 Jersey 中注册了注入感知,Validator并注册到我们的服务容器中,这样您就可以@Inject Validator在任何地方随心所欲地使用它。