我已经按照Scala Play和Akka演员创建Web套接字的示例:
恢复时,控制器:
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个连接,创建的actor是:
我想改变演员'名称基于Web套接字消息的字段。我怎么能这样做?。
答案 0 :(得分:4)
您可以按如下方式设置actor的名称:
创建一个文件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))
}
}
使用BetterActorFlow而不是ActorFlow:
BetterActorFlow.actorRef(out =>
ChatActor.props(out), 16, OverflowStrategy.dropNew, Some("alicebob"))
这对我有用。创建的actor位于user/alicebob
(使用此context.system.actorSelection("user/alicebob")
)
答案 1 :(得分:3)
根据ActorFlow的源代码,目前无法确定为连接产生的实际actor的名称(第38行):
Sink.actorRef(factory.actorOf(Props(new Actor { ... }) /*, name parameter is omitted */)
但是,ActorFlow.actorRef
接受隐式ActorRefFactory
,在代码中的所有情况下均为implicit system: ActorSystem
。我们知道,有两个最常见的ActorRefFactories:ActorSystem
和ActorContext
。您可以修改代码,以便每次接受连接时,另一个虚拟演员将使用您的首选名称(例如myActor1
)生成,并将此新演员的context
传递给{ {1}}而是。作为回报,连接的参与者将按如下命名: