我不知道如何将服务注入Actor。
我尝试了几种方法,认为这一种最适合。
我认为主要的问题是,我将websocket作为参数提供给后续参与者。当我将Inject拉到类时,由于签名冲突,签名编译不执行。我尝试添加一个currying隐式类声明来注入服务,但也没有成功。
我该怎么做才能把它做好?
运行此代码会导致NullPointerException。
package actors
import akka.actor._
import com.google.inject.Inject
import play.api.libs.json._
import models._
import services.WeatherService
/**
* Created by jbc on 28.12.16.
*/
class WeatherWSActor (out: ActorRef) extends Actor {
@Inject() val weatherService: WeatherService = null
def handleMessage(msg: JsValue): JsValue = {
val req = msg.as[Request]
req match {
case Request("daily") => Json.toJson(weatherService.getFourDays())
case Request("next") => Json.toJson(weatherService.getNextHour())
}
}
override def receive: Receive = {
case msg: JsValue => out ! handleMessage(msg)
case _ => out ! "Bad Request"
}
@scala.throws[Exception](classOf[Exception])
override def postStop(): Unit = {
}
}
object WeatherWSActor {
def props(out: ActorRef) = Props(new WeatherWSActor(out))
}
控制器代码:
class WeatherWSController @Inject() (implicit system: ActorSystem, materializer: Materializer) extends Controller {
def socket = WebSocket.accept[JsValue, JsValue] { request =>
ActorFlow.actorRef(out => WeatherWSActor.props(out));
}
}
使用此模块代码设置服务
class Module extends AbstractModule {
override def configure(): Unit = {
bind(classOf[WeatherService]).to(classOf[WeatherServiceImpl]).asEagerSingleton()
}
}
这在文档中有所介绍,但这里有一个摘要。
如果你想注入你的演员,你需要改变一些事情。首先,注入点是构造函数,所以
class WeatherWSActor (out: ActorRef) extends Actor {
@Inject() val weatherService: WeatherService = null
// ...
}
应该成为
class WeatherWSActor @Inject() (out: ActorRef,
weatherService: WeatherService) extends Actor {
// ...
}
事实上,将null
分配给Scalaval
也会给您带来问题。
其次,为参与者声明一个绑定,而不是自己创建它。
import com.google.inject.AbstractModule
import play.api.libs.concurrent.AkkaGuiceSupport
import actors.WeatherWSActor
class MyModule extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[WeatherWSActor]("weather-actor")
}
}
附带说明一下,您还需要为out
创建一个命名绑定,并更改WeatherWSActor
的定义以反映这一点:
class WeatherWSActor @Inject() (@javax.inject.Named("out-actor") out: ActorRef,
weatherService: WeatherService) extends Actor {
// ...
}
out-actor
是您在模块中设置的任何一个类,例如
class MyModule extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[WeatherWSActor]("weather-actor")
bindActor[SomeOutActor]("out-actor")
}
}
但是
由于在创建web套接字时您将获得out
,因此(可能)您将拥有多个WeatherWSActor
实例。这将影响如何处理依赖项注入,因此,不注入outActor
(因此不为其创建绑定),而是使用一个向actor系统中某个点寻址的OutActor
的所有实例广播的单例WeatherWSActor
更有意义。