1

我在使用 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 根本没有被注入。我缩小了问题的范围。似乎调用了默认构造函数而不是使用依赖注入。根据这篇文章,这可以通过使用自定义 ConstraintValidatorFactory 来更改。

现在我有以下两个问题:

  1. 即使提供了指向休眠文档的链接,我也不知道如何实现这样的工厂以使 DI 正常工作。
  2. 我在哪里注册/绑定/(“随便”)我的工厂在 ninja 框架中?
4

1 回答 1

2

由于您的 PlayerIdValidator 没有使用 guice 实例化,因此您将无法在该类中启用依赖注入。您可以使用使用注射器的替代解决方案。

要存储您的注入器引用,您可以使用 Singleton - 这里我使用枚举来实现它:

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);
}
于 2017-05-04T05:49:40.193 回答