这是一个基本问题,但谷歌搜索几个小时后我找不到令人满意的答案。从here中的示例来看,制作Web套接字的方法是这样的:
控制器代码:
import play.api.mvc._
import play.api.libs.streams.ActorFlow
import javax.inject.Inject
import akka.actor.ActorSystem
import akka.stream.Materializer
class Application @Inject()(cc:ControllerComponents) (implicit system: ActorSystem, mat: Materializer) extends AbstractController(cc) {
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发送一个字符串块。如何从控制器代码将此字符串发送到上面的actor?
答案 0 :(得分:0)
首先让我们了解已经创建的内容以及需要添加的内容。 =IF(AND(I5<0,05;0,05);IF(AND(I5>0,05;I5);IF(AND(I5>0,4;0,4);IF(AND(I5<0,4;I5);""))))
的类型是WebSocket
。
此socket
揭示了一个WebSocket
方法:
apply
因此,只要您没有发送消息,就尚未创建流。现在,一旦发送了一条消息,我们就可以创建流程并发送一条消息:
def apply(request: RequestHeader): Future[Either[Result, Flow[Message, Message, _]]]
答案 1 :(得分:0)
此sample app和related discussion可能会有所帮助。以下是从链接的示例应用程序中裁剪/总结的一些代码:
Flow.futureFlow(futureUserActor.map { userActor =>
val incomingMessages: Sink[Message, NotUsed] =
Flow[Message]
.map(...)
.to(...)
val outgoingMessages: Source[Message, NotUsed] =
ActorSource
.actorRef[User.OutgoingMessage](...)
.mapMaterializedValue { outActor =>
// give the user actor a way to send messages out
userActor ! User.Connected(outActor)
NotUsed
}
.map(...)
// then combine both to a flow
Flow.fromSinkAndSourceCoupled(incomingMessages, outgoingMessages)
})
答案 2 :(得分:0)
至少有两种方法可以解决此问题:
ActorFlow.actorRef
方法以返回基础参与者。之前有一个similar discussion,这里是gist。如果将基础参与者放入(用户,websocket)映射中,请确保使用诸如TrieMap之类的线程安全实现。sealed trait AppEvent
final case class ButtonClicked(user: User.ID) extends AppEvent
// inside an action
system.eventStream.publish(ButtonClicked(request.identity.id))
// inside your actor
override def preStart =
context.system.eventStream.subscribe(self, classOf[AppEvent])
请注意,事件总线的概念是抽象的。我上面展示的是使用akka的classic event bus(在本地工作)的最基本方法。对于这种扩展方法,您需要在幕后有一个实际的消息队列。