Java Dropwizard 初始化 ConstraintValidator
Java Dropwizard initialize ConstraintValidator
假设我有一个自定义 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) {
}
}
我希望能够通过从 Dropwizard run
或 initialize
中的 ServiceConfiguration
传递一些配置来初始化此 class。
这可能吗?
首先,值得注意的是即将发布的 Dropwizard 2.0.0 版本 built in support for this
现在,这个过程有点复杂。您基本上想要重新bootstrap Hibernate 验证,但使用支持注入的自定义约束验证器工厂。
它将涉及大约 4 个自定义 classes,所以请耐心等待。这里是:
首先,我们首先注册一个自定义功能以将此功能包装到我们的 Application
class:
public void run(MainConfiguration config, Environment environment) throws Exception {
// ...
environment.jersey().register(InjectingValidationFeature.class);
}
现在我们定义功能: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;
}
}
现在我们定义那些我们在上面注册的 classes。让我们从核心部分开始,InjectingConstraintValidatorFactory
是 Hibernate 验证器实际用来创建约束验证器的部分。请注意,因为我们在容器中注册它们,我们实际上已经可以开始注入东西了,这里是我们的自定义 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);
}
}
现在我们工厂的中央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
}
}
最后,我们的 InjectingConfiguredValidator
,请注意它是如何仅使用 DropwizardConfiguredValidator
但带有 @Inject
的 @Inject
这将使我们能够从上面的 ValidatorFactory
接收验证器:
public class InjectingConfiguredValidator extends DropwizardConfiguredValidator {
@Inject
public InjectingConfiguredValidator(Validator validator) {
super(validator);
}
}
就是这样。通过以上内容,我们成功地在 Jersey 和我们的服务容器中注册了一个注入感知 Validator
,因此您也可以在任何地方 @Inject Validator
并随心所欲地使用它。
假设我有一个自定义 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) {
}
}
我希望能够通过从 Dropwizard run
或 initialize
中的 ServiceConfiguration
传递一些配置来初始化此 class。
这可能吗?
首先,值得注意的是即将发布的 Dropwizard 2.0.0 版本 built in support for this
现在,这个过程有点复杂。您基本上想要重新bootstrap Hibernate 验证,但使用支持注入的自定义约束验证器工厂。
它将涉及大约 4 个自定义 classes,所以请耐心等待。这里是:
首先,我们首先注册一个自定义功能以将此功能包装到我们的 Application
class:
public void run(MainConfiguration config, Environment environment) throws Exception {
// ...
environment.jersey().register(InjectingValidationFeature.class);
}
现在我们定义功能: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;
}
}
现在我们定义那些我们在上面注册的 classes。让我们从核心部分开始,InjectingConstraintValidatorFactory
是 Hibernate 验证器实际用来创建约束验证器的部分。请注意,因为我们在容器中注册它们,我们实际上已经可以开始注入东西了,这里是我们的自定义 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);
}
}
现在我们工厂的中央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
}
}
最后,我们的 InjectingConfiguredValidator
,请注意它是如何仅使用 DropwizardConfiguredValidator
但带有 @Inject
的 @Inject
这将使我们能够从上面的 ValidatorFactory
接收验证器:
public class InjectingConfiguredValidator extends DropwizardConfiguredValidator {
@Inject
public InjectingConfiguredValidator(Validator validator) {
super(validator);
}
}
就是这样。通过以上内容,我们成功地在 Jersey 和我们的服务容器中注册了一个注入感知 Validator
,因此您也可以在任何地方 @Inject Validator
并随心所欲地使用它。