2016-05-17 93 views
2

我是按照使用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套接字消息的字段中的角色名稱。我怎麼能這樣做?

回答

2

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

2

您可以設置名稱演員如下:

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