Actor中的WebSocket.acceptWithActor和@Inject()(Play 2.5)

时间:2017-08-19 17:32:57

标签: dependency-injection playframework akka guice playframework-2.5

WebSocket.acceptWithActor在没有使用Guice的情况下实例化一个新的Akka演员。

使用Play 2.4,通过导入play.api.Play.current仍然可以使用我的演员的注入器。

来自ReactiveMongo documentation的片段:

import scala.concurrent.Future

import play.api.Play.current // should be deprecated in favor of DI
import play.api.libs.concurrent.Execution.Implicits.defaultContext

import play.modules.reactivemongo.ReactiveMongoApi
import play.modules.reactivemongo.json.collection.JSONCollection

object Foo {
  lazy val reactiveMongoApi = current.injector.instanceOf[ReactiveMongoApi]

  def collection(name: String): Future[JSONCollection] =
    reactiveMongoApi.database.map(_.collection[JSONCollection](name))
}

但是在Play 2.5中,play.api.Play.current已被弃用。我怎样才能在我的演员中注入ReactiveMongoApi?在我的演员中使用ReactiveMongoApi实例的推荐方法是什么?

以下是适用于Play 2.4的代码,因为我的自定义角色类ClientActor可以通过ReactiveMongoApi访问current.injector.instanceOf[ReactiveMongoApi]

@Singleton
class Application @Inject() (system: ActorSystem) extends Controller {

  val midiDiscoveryActor = system.actorOf(MidiDiscoveryActor.props, "midi-discovery-actor")
  val midiActor = system.actorOf(MidiActor.props(midiDiscoveryActor), "midi-actor")

  def index(page: String) = Action {
    Ok(views.html.index(page))
  }

  def bidirectional = WebSocket.acceptWithActor[JsValue, JsValue] { request => out =>
    ClientActor.props(out, midiActor, midiDiscoveryActor)
  }

}

2 个答案:

答案 0 :(得分:3)

我不认为这是可能的。引用James Roper

  

Play为依赖注入actor提供的助手适用于有限数量的用例。虽然,帮助者实际上只是非常薄的包装超过了一些常见的要求 - 根本不需要它们。在Play的WebSocket actor支持的情况下,事情是,通常你想手动实例化actor,因为你必须以某种方式将它传递给ActorRef。所以,您可以使用Guice辅助注入执行此操作,并定义一个因子接口,该接口使用out actor ref(以及您想要传递给它的任何其他参数),或者只是手动实例化它,将依赖项从控制器传递给actor ,例如:

class MyController @Inject() (myDep: MyDep) extends Controller {
  def socket = WebSocket.acceptWithActor[String, String] { request => out =>
    MyWebSocketActor.props(out, myDep)
  }
}

答案 1 :(得分:0)

Play 2.5内置支持DI。

需要修改MidiActor签名,如下所述。

class MidiActor@Inject() (configuration: Configuration,  @Named("midi-discovery-actor") midiDiscoveryActor: ActorRef) extends Actor with InjectedActorSupport{
.......
}

创建新模块并在application.conf中启用

play.modules.enabled += MyModule

class MyModule extends AbstractModule with AkkaGuiceSupport {
  def configure = {
    bindActor[MidiDiscoveryActor]("midi-discovery-actor")
    bindActor[MidiActor]("midi-actor")
  }
}

按以下方式更改您的控制器

@Singleton
class Application @Inject() (system: ActorSystem,@Named("midi-actor") midiActor: ActorRef,
@Named("midi-discovery-actor") midiDiscoveryActor: ActorRef) (implicit ec: ExecutionContext)  extends Controller {

  def index(page: String) = Action {
    Ok(views.html.index(page))
  }

  def bidirectional = WebSocket.acceptWithActor[JsValue, JsValue] { request => out =>
    ClientActor.props(out, midiActor, midiDiscoveryActor)
  }

}