【问题标题】:Play 2.4 create an actor for handle websocket with GuicePlay 2.4 用Guice创建一个actor来处理websocket
【发布时间】:2016-08-16 08:20:56
【问题描述】:

首先感谢大家抽出一些时间来查看我的问题。我是 scala 生态系统的新手,所以我认为我混淆了一些概念。

我在 Play 2.4 项目中引入 Guice,它在一些 REST 控制器中运行。我已编辑 build.sbt 以附加 routesGenerator := InjectedRoutesGenerator 作为 Play 官方文档建议并编辑了我的路线,如下例所示:

GET        /socket       @com.letgo.chat.controllers.ChatController.socket

我的注入 actor 的模块如下所示:

class ChatModule extends AbstractModule with ScalaModule with AkkaGuiceSupport with GuiceAkkaActorRefProvider {
  override def configure() {

    bindActor[TalkerProviderActor](TalkerProviderActor.name)
    ...

所有这些似乎都在起作用。

但另一个端点使用 Play 方法 WebSocket.acceptWithActor 处理 websocket。我需要创建一个actor,它也需要一些依赖项。

控制器创建一个ConnectionActor:

class ConnectionActor(
  @Assisted() websocket: ActorRef,
  monitoring: Monitoring,
  @Named(BouncerActor.name) bouncer: ActorRef,
) extends Actor

...

class ChatController @Inject() extends Controller {
  def socket(): WebSocket[String, JsValue] = WebSocket.acceptWithActor[String, JsValue] { request => out =>
    // I had the following statement in order to build the actor before introducing Guice:
    // ConnectionActor.props()
    // Now, I need some magic here
  }
}

如您所见,我需要一个 websocket: ActorRef 用于 websocket 输出。

我使用AkkaGuiceSupport提供的bindActorFactory方法在应用程序的其他部分创建了一些actor:

bindActorFactory[TalkerActor, TalkerActor.Factory]

但我不知道在这种情况下我应该如何创建一个处理 websocket 的参与者。你们能帮帮我吗?

谢谢

【问题讨论】:

    标签: scala playframework playframework-2.0 akka guice


    【解决方案1】:

    我相信这可以解决问题:

    package controllers
    
    import javax.inject._
    
    import akka.actor.{Actor, ActorRef, ActorSystem, Props}
    import akka.stream.Materializer
    import play.api.libs.streams.ActorFlow
    import play.api.libs.ws.WSClient
    import play.api.mvc._
    
    import scala.concurrent.ExecutionContext.Implicits.global
    
    @Singleton
    class SocketActorProvider @Inject() (ws: WSClient) {
      def get(out: ActorRef) = Props(new SocketActor(out, ws))
    }
    
    class SocketActor(out: ActorRef, ws: WSClient) extends Actor {
      override def receive: Receive = {
        case "ping" => ws.url("http://localhost:9000/pong").get().foreach(pong => out ! pong.body)
      }
    }
    
    @Singleton
    class HomeController @Inject() (implicit system: ActorSystem, ws: WSClient, materializer: Materializer, provider: SocketActorProvider) extends Controller {
    
      // route '/ws'
      def socket = WebSocket.accept[String, String] { request =>
        ActorFlow.actorRef(out => provider.get(out))
      }
    
      // route '/pong'
      def pong = Action {
        Ok("PONG!")
      }
    
      // route '/'
      def index = Action {
        Ok("""
          <script>
            var ws = new WebSocket('ws://localhost:9000/ws');
            ws.onopen = () => console.log('I am open!');
            ws.onmessage = m => console.log(m.data);
    
            setInterval(() => {console.log('ping'); ws.send('ping')}, 1000)
          </script>
        """).as("text/html")
      }
    
    }
    

    如您所见,Guice 注入了一个提供 WSClient 的提供程序,并且在构建一个参与者时它传递了依赖项

    【讨论】:

      猜你喜欢
      • 2016-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-20
      • 2018-07-31
      • 2017-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多