首先,感谢大家花些时间来回顾我的问题。我是scala生态系统的新手,所以我觉得我在讨论一些概念。
我在Play 2.4项目中介绍了Guice,它在一些REST控制器中工作。我编辑了build.sbt以附加routesGenerator := InjectedRoutesGenerator
作为Play官方文档推荐并编辑我的路线,如下例所示:
GET /socket @com.letgo.chat.controllers.ChatController.socket
我注入演员的模块如下:
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输出。
我使用bindActorFactory
提供的AkkaGuiceSupport
方法在应用程序的其他部分创建了一些actor:
bindActorFactory[TalkerActor, TalkerActor.Factory]
但我不知道在这种情况下我应该如何创建一个处理websocket的actor。你能帮助我吗?
谢谢
答案 0 :(得分:3)
我相信这可以解决问题:
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,在构建一个actor时它传递了依赖