我正在设置游戏!我们的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可用于该范围(暗示?我不知道)。如果这是不可能的,那么无论如何增加该样本顶部的噪声量将会起作用。感谢
答案 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