16

从 Play Framework 2.4 开始,就有可能使用依赖注入(使用 Guice)。

在我的 ActionBuilders 中使用对象(例如AuthenticationService)之前:

object AuthenticatedAction extends ActionBuilder[AuthenticatedRequest] {
  override def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[Result]): Future[Result] = {
    ...
    AuthenticationService.authenticate (...)
    ...
  }
}

现在AuthenticationService不再是一个对象,而是一个类。我怎样才能仍然使用AuthenticationService我的ActionBuilder

4

3 回答 3

28

在 trait 中定义您的操作构建器,并将身份验证服务作为抽象字段。然后将它们混合到您的控制器中,然后将服务注入其中。例如:

trait MyActionBuilders {
  // the abstract dependency
  def authService: AuthenticationService

  def AuthenticatedAction = new ActionBuilder[AuthenticatedRequest] {
    override def invokeBlock[A](request: Request[A], block(AuthenticatedRequest[A]) => Future[Result]): Future[Result] = {
      authService.authenticate(...)
      ...
    }
  }
}

和控制器:

@Singleton
class MyController @Inject()(authService: AuthenticationService) extends Controller with MyActionBuilders {    
  def myAction(...) = AuthenticatedAction { implicit request =>
    Ok("authenticated!")
  }
}
于 2015-06-28T11:56:54.193 回答
18

我不喜欢上面示例中要求继承的方式。但显然可以简单地包装一个object内部类:

class Authentication @Inject()(authService: AuthenticationService) {
  object AuthenticatedAction extends ActionBuilder[Request] {
    def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
      // Do your thing wit the authService...
      block(request)
    }
  }
}

class YourController @Inject() (val auth: Authentication) extends Controller (
  def loggedInUser = auth.AuthenticatedAction(parse.json) { implicit request =>
    // ...
  }
}
于 2015-09-13T16:02:23.457 回答
0

我喜欢接受的答案,但由于某种原因,编译器无法识别 authService 参考。只需在方法签名中发送服务,我就很容易解决这个问题,一个...

class Authentication @Inject()(authenticationService: AuthenticationService) extends Controller with ActionBuilders {

  def testAuth = AuthenticatedAction(authenticationService).async { implicit request =>
    Future.successful(Ok("Authenticated!"))
  }

}
于 2015-08-23T18:33:27.737 回答