Play Framework: Dependency Inject Action Builder

白昼怎懂夜的黑 提交于 2019-12-17 23:27:34

问题


since Play Framework 2.4 there is the possibility to use dependency injection (with Guice).

Before I used objects (for example AuthenticationService) in my ActionBuilders:

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

Now AuthenticationService is not an object anymore, but a class. How can I still use the AuthenticationService in my ActionBuilder?


回答1:


Define your action builders inside a trait with the authentication service as an abstract field. Then mix them into your controllers, into which you inject the service. For example:

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(...)
      ...
    }
  }
}

and the controller:

@Singleton
class MyController @Inject()(authService: AuthenticationService) extends Controller with MyActionBuilders {    
  def myAction(...) = AuthenticatedAction { implicit request =>
    Ok("authenticated!")
  }
}



回答2:


I didn't like the way one was required to inherit in the above example. But apparently it's possible to simply wrap a object inside class:

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



回答3:


I like accepted answer but for some reason the compiler would not recognize the authService reference. I got around this pretty easily by just sending the service in the method signature, a la...

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

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

}


来源:https://stackoverflow.com/questions/31098911/play-framework-dependency-inject-action-builder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!