播放斯卡拉阿卡的WebSockets改变演员路径

播放斯卡拉阿卡的WebSockets改变演员路径

问题描述:

我是按照使用Scala创建Web套接字播放和阿卡演员的例子:播放斯卡拉阿卡的WebSockets改变演员路径

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) 
    } 
} 

演员创建(每个websocket一个连接)是/用户角色的孩子。我创建了3个连接,创造了男演员依次为:

  1. /用户/ $ B
  2. /用户/ $ C
  3. /用户/ $ d

我想改变基于Web套接字消息的字段中的角色名称。我怎么能这样做?

ActorFlow源代码,它是目前无法thange实际演员的名称的连接产生了(线38):

Sink.actorRef(factory.actorOf(Props(new Actor { ... }) /*, name parameter is omitted */) 

然而,ActorFlow.actorRef接受一个隐含ActorRefFactory,其在代码中的所有情况下都是implicit system: ActorSystem。我们知道,有2个最常见的ActorRefFactory:ActorSystemActorContext。您可以修改代码,以便每次连接被接受时,另一个虚拟演员会产生您的首选名称(例如myActor1),然后将此新演员的context改为ActorFlow.actorRef。作为回报,演员的连接将被命名如下:

  • /用户/ myActor1/$一个
  • /用户/ myActor2/$一个
+1

有没有办法让'ActorFlow.actoRef'创建的actorRef被创建为特定Actor的子元素? 我想让它成为所有websocket演员都是我可以用来协调它们的主演员的子项。 – Nathan

您可以设置名称演员如下:

  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")一起使用)