播放actor sender()在从websocket actor接收时返回自身

时间:2016-04-01 05:49:49

标签: scala playframework actor playframework-2.5

我正在使用Play 2.5。我正在使用Websocket actor将消息发送给Routes Actor。但是,当在路由上收到msg时,sender()方法返回Routes本身而不是该Websocket actor。

申请表如下

@Singleton
class Application @Inject()(implicit val system: ActorSystem,
                            implicit val wsClient: WSClient,
                            implicit val config: Configuration,
                            implicit val materializer: Materializer) extends Controller {
...
  lazy val routesActor = system.actorOf(Props(classOf[RoutesActor]), "routes")

  def ws = WebSocket.accept[JsValue, JsValue] { request =>
    ActorFlow.actorRef(out => UserActor.props(out)(routesActor))
  }

...
}

UserActor:

class UserActor(out: ActorRef)(implicit val RoutesActor: ActorRef) extends Actor with ActorLogging {

  def receive() = {
    case json: JsValue => {
      val parsedQuery = parseQuery(json)
      cachesActor ! (parsedQuery, self)
      log.info("this user is:" + self)
    }
  }

路线演员

class RoutesActor extends Actor with ActorLogging {
  def receive = {
    case (q: ParsedQuery, out: ActorRef) => {
      log.info("Routes:" + self + " get query from : " + sender() + " actually is:" + out)
    }
  }
}

log.info打印了以下行:

  

[info] a.RoutesActor - 路由:演员[akka:// application / user / routes#854844162]获取查询:Actor [akka:// application / user / routes#854844162]实际上是:Actor [akka ://应用/用户/ $ b / flowActor#-75193340]

如您所见,sender()指向自身而不是flowActor。因此,我不能使用sender()来回复消息。这让我很困惑。有没有人有一些想法在这里出错?

1 个答案:

答案 0 :(得分:2)

tell的签名是def !(message: Any)(implicit sender: ActorRef): Unit,因此消息的发送者通过隐式参数获取。当您从UserActor内发送消息时,这是implicit val RoutesActor: ActorRef,它被定义为类参数。

如果您想将UserActor用作发件人,请从参数列表中删除隐含关键字,或明确提供self作为发件人:cachesActor.tell((parsedQuery, self), self)

如果您想使用sender()中也是UserActor的原始发件人,则可以改为使用forwardcachesActor.forward((parsedQuery, self))。这将明确使用context.sender()而不是隐式RoutesActor作为邮件的发件人。