玩 Scala Akka WebSockets 更改 actor 路径

2024-05-02

我遵循使用 Scala Play 和 Akka Actor 创建 Web 套接字的示例:

https://www.playframework.com/documentation/2.5.x/ScalaWebSockets#Handling-WebSockets-with-Akka-Streams-and-actors https://www.playframework.com/documentation/2.5.x/ScalaWebSockets#Handling-WebSockets-with-Akka-Streams-and-actors

恢复时,控制器:

import play.api.mvc._
import play.api.libs.streams._

class Controller1 @Inject() (implicit system: ActorSystem, materializer: Materializer) {

  def socket = WebSocket.accept[String, String] { request =>
    ActorFlow.actorRef(out => MyWebSocketActor.props(out))
  }

还有演员:

import akka.actor._

object MyWebSocketActor {
  def props(out: ActorRef) = Props(new MyWebSocketActor(out))
}

class MyWebSocketActor(out: ActorRef) extends Actor {
  def receive = {
    case msg: String =>
      out ! ("I received your message: " + msg)
  }
}

创建的 actor(每个 websocket 连接一个)是 /user actor 的子级。我创建了 3 个连接,创建的参与者是:

  1. /user/$b
  2. /user/$c
  3. /user/$d

我想根据网络套接字消息的字段更改演员的姓名。我怎么能这样做呢?


您可以按如下方式设置演员的姓名:

  1. 创建文件 BetterActorFlow.scala

    package your.package
    
    import akka.actor._
    import akka.stream.scaladsl.{Keep, Sink, Source, Flow}
    import akka.stream.{Materializer, OverflowStrategy}
    
    object BetterActorFlow {
    
      def actorRef[In, Out](props: ActorRef => Props, bufferSize: Int = 16, overflowStrategy: OverflowStrategy = OverflowStrategy.dropNew, maybeName: Option[String] = None)(implicit factory: ActorRefFactory, mat: Materializer): Flow[In, Out, _] = {
    
        val (outActor, publisher) = Source.actorRef[Out](bufferSize, overflowStrategy)
                            .toMat(Sink.asPublisher(false))(Keep.both).run()
    
        def flowActorProps: Props = {
          Props(new Actor {
            val flowActor = context.watch(context.actorOf(props(outActor), "flowActor"))
    
            def receive = {
              case Status.Success(_) | Status.Failure(_) => flowActor ! PoisonPill
              case Terminated(_) => context.stop(self)
              case other => flowActor ! other
            }
    
            override def supervisorStrategy = OneForOneStrategy() { case _ => SupervisorStrategy.Stop }
          })
        }
    
        def actorRefForSink =
          maybeName.fold(factory.actorOf(flowActorProps)) { name => factory.actorOf(flowActorProps, name) }
    
        Flow.fromSinkAndSource(Sink.actorRef(actorRefForSink, Status.Success(())), Source.fromPublisher(publisher))
    
      }
    }
    
  2. 使用 BetterActorFlow 代替 ActorFlow:

    BetterActorFlow.actorRef(out =>
      ChatActor.props(out), 16, OverflowStrategy.dropNew, Some("alicebob"))
    

这对我有用。创建的演员位于user/alicebob(将此与context.system.actorSelection("user/alicebob"))

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

玩 Scala Akka WebSockets 更改 actor 路径 的相关文章

随机推荐