如何在 Ninjaframework 的 ConstraintValidator 中使用依赖注入?
How to use Dependency Injection in a ConstraintValidator in Ninjaframework?
我在使用 ninja 框架 (6.0.0-rc1) 和自定义 ConstraintValidator 验证 POST 请求时遇到问题。
这是我当前的实现:
@Singleton
public class GameController {
public Result postGame(@JSR303Validation final GameRequestObject gameRequestObject, final Validation validation) {
if(validation.hasViolations()){
return Results.json().render(validation.getViolations());
}
//... code to save game to DB etc ...
return Results.ok();
}
}
public class GameRequestObject {
@ValidPlayerId // - Custom validation constraint
private long playerId;
//... getter, setter etc ...
}
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = PlayerIdValidator.class)
public @interface @ValidPlayerId {
String message() default "{ch.some.label.here}";
Class[] groups() default {};
Class[] payload() default {};
}
public class PlayerIdValidator implements ConstraintValidator {
@Inject // - Does not work
private PlayerDao playerDao; // - Is always null
public void initialize(ValidPlayerId validPlayerId) {}
public boolean isValid(Long value, ConstraintValidatorContext context) {
return playerDao != null && playerDao.isPlayerIdValid(value);
}
}
问题是,根本没有注入 playerDao。我缩小了问题范围。似乎调用了默认构造函数而不是使用依赖注入。根据 this post 这可以通过使用自定义 ConstraintValidatorFactory 来改变。
现在我有以下两个问题:
- 即使提供了 link 休眠文档,我也不知道如何实现这样的工厂以使 DI 正常工作。
- 我在 ninja 框架中的哪里注册/绑定/(“随便”)我的工厂?
由于您的 PlayerIdValidator 不是使用 guice 实例化的,因此您将无法在 class 中启用依赖注入。您可以使用使用注射器的替代解决方案。
要存储您的注入器引用,您可以使用单例 - 在这里我使用枚举来实现它:
public enum InjectorProvider {
INSTANCE;
private Injector injector;
public Injector getInjector() {
return injector;
}
public void setInjector(Injector injector) {
this.injector = injector;
}
}
我不知道你是如何初始化guice的,但你可能有这样的代码,所以添加代码来存储注入器:
Injector injector = Guice.createInjector(...your modules...);
InjectorProvider.INSTANCE.setInjector(injector);
现在使用此提供程序获取注入器并实例化 PlayerDao:
public boolean isValid(Long value, ConstraintValidatorContext context) {
Injector injector = InjectorProvider.INSTANCE.getInjector();
PlayerDao playerDao = injector.getInstance(PlayerDao.class);
return playerDao != null && playerDao.isPlayerIdValid(value);
}
我在使用 ninja 框架 (6.0.0-rc1) 和自定义 ConstraintValidator 验证 POST 请求时遇到问题。
这是我当前的实现:
@Singleton
public class GameController {
public Result postGame(@JSR303Validation final GameRequestObject gameRequestObject, final Validation validation) {
if(validation.hasViolations()){
return Results.json().render(validation.getViolations());
}
//... code to save game to DB etc ...
return Results.ok();
}
}
public class GameRequestObject {
@ValidPlayerId // - Custom validation constraint
private long playerId;
//... getter, setter etc ...
}
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = PlayerIdValidator.class)
public @interface @ValidPlayerId {
String message() default "{ch.some.label.here}";
Class[] groups() default {};
Class[] payload() default {};
}
public class PlayerIdValidator implements ConstraintValidator {
@Inject // - Does not work
private PlayerDao playerDao; // - Is always null
public void initialize(ValidPlayerId validPlayerId) {}
public boolean isValid(Long value, ConstraintValidatorContext context) {
return playerDao != null && playerDao.isPlayerIdValid(value);
}
}
问题是,根本没有注入 playerDao。我缩小了问题范围。似乎调用了默认构造函数而不是使用依赖注入。根据 this post 这可以通过使用自定义 ConstraintValidatorFactory 来改变。
现在我有以下两个问题:
- 即使提供了 link 休眠文档,我也不知道如何实现这样的工厂以使 DI 正常工作。
- 我在 ninja 框架中的哪里注册/绑定/(“随便”)我的工厂?
由于您的 PlayerIdValidator 不是使用 guice 实例化的,因此您将无法在 class 中启用依赖注入。您可以使用使用注射器的替代解决方案。
要存储您的注入器引用,您可以使用单例 - 在这里我使用枚举来实现它:
public enum InjectorProvider {
INSTANCE;
private Injector injector;
public Injector getInjector() {
return injector;
}
public void setInjector(Injector injector) {
this.injector = injector;
}
}
我不知道你是如何初始化guice的,但你可能有这样的代码,所以添加代码来存储注入器:
Injector injector = Guice.createInjector(...your modules...);
InjectorProvider.INSTANCE.setInjector(injector);
现在使用此提供程序获取注入器并实例化 PlayerDao:
public boolean isValid(Long value, ConstraintValidatorContext context) {
Injector injector = InjectorProvider.INSTANCE.getInjector();
PlayerDao playerDao = injector.getInstance(PlayerDao.class);
return playerDao != null && playerDao.isPlayerIdValid(value);
}