Play框架:依赖注入Action Builder

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不再是对象,而是一个类。我如何在ActionBuilder中仍然使用AuthenticationService

3个回答

28

在一个trait中定义你的action builders,并将身份验证服务作为抽象字段。然后将它们混合到你的控制器中,在其中注入该服务。例如:

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!")
  }
}

3
MyController 中,在 authService 前面添加 val 关键字,否则编译器会报错,提示 authService 方法未定义。 - Isammoc
无论是使用val还是def,这对我都不起作用,它说Controller类需要是抽象的,因为未定义def/val。 - Daniel

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 =>
    // ...
  }
}

0

我喜欢被接受的答案,但由于某些原因编译器无法识别authService引用。我很容易地通过在方法签名中发送服务来解决这个问题,就像...

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

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

}

我刚刚检查了一下,我没有看到任何原因使得被接受的答案无法编译! - Tim Joseph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接