Play framework + Scala:使用Action Composition注入依赖项

时间:2014-10-23 19:26:47

标签: scala dependency-injection playframework

我正在设置游戏!我们的API的应用程序。此API封装了不同的服务。我想在一个动作中注入这些服务,但只注入该特定端点所需的服务。类似的东西:

object Application extends Controller {
  def index = (UsersAction andThen OrdersAction) {
    // boom UsersService and OrdersService is available here
    for {
      users <- usersService.list
      orders <- ordersService.list
    } yield "whatever"
  }
}

我一直在玩这个想法并使用ActionTransformers我能够将传入的请求转换为具有给定服务的请求,但是我不知道如何能够完成那么通用,所以我可以编写这些在没有为WrapperRequests的所有可能组合创建ActionTransformer的情况下以任意顺序执行操作。

也许动作组合不是实现这一目标的最佳方式。我听见了。

谢谢

更新

为了澄清,上面的代码是伪代码,这是理想的场景,其中usersService和ordersService可用于该范围(暗示?我不知道)。如果这是不可能的,那么无论如何增加该样本顶部的噪声量将会起作用。感谢

2 个答案:

答案 0 :(得分:1)

我最接近你的问题的是:

def index =
  new UsersAction with OrdersAction {
    def body =
      for {
        users <- userService.list
        orders <- orderService.list
      } yield Ok("whatever")
  }

实施非常简单

trait CustomAction extends Action[AnyContent] {
  def body: Future[Result]

  def apply(request: Request[AnyContent]): Future[Result] = body
  val parser = BodyParsers.parse.anyContent
}

trait UsersAction extends CustomAction {
  val userService: UserService = ???
}
trait OrdersAction extends CustomAction {
  val orderService: OrderService = ???
}

这些是我用来编译它的其他部分:

trait User
trait Order

trait UserService {
  def list: Future[Seq[User]]
}

trait OrderService {
  def list: Future[Seq[Order]]
}

答案 1 :(得分:0)

你可以用guice,spring或者你想要的东西注射。 guice的例子。 只需将对象更改为类:

class Application @Inject(userAction:UsersAction,ordersAction:OrdersAction) extends Controller {
  def index = (UsersAction andThen OrdersAction) {
    // boom UsersService and OrdersService is available here
    for {
      users <- usersService.list
      orders <- ordersService.list
    } yield "whatever"
  }
}

您必须在Global中覆盖:

object Global extends GlobalSettings{

 private lazy val injector = Guice.createInjector(new CommonModule)

 override def getControllerInstance[A](clazz: Class[A]) = {
    injector.getInstance(clazz)
  }

}
class CommonModule extends AbstractModule{

  protected def configure() {
    bind(classOf[UsersAction]).to(classOf[UsersActionImpl])
    bind(classOf[OrdersAction]).to(classOf[OrdersActionImpl])
  }

}

在路线文件中将@添加到控制器:

GET /service  @controllers.Application.index