如何使用Play framework 2.6创建WebSockets



我正在尝试使用Play Framework 2.6执行以下操作:

  1. 浏览器以服务器为目标,并创建WebSocket
  2. 稍后(在执行一些其他请求之后(,服务器通过之前创建的WebSocket向浏览器发送消息

点1可以通过一条路线轻松完成:

public WebSocket socket() {
return WebSocket.Text.accept(request -> {
// Log events to the console
Sink<String, ?> in = Sink.foreach(System.out::println);
// Send a single 'Hello!' message and then leave the socket open
Source<String, ?> out = Source.single("Hello!").concat(Source.maybe());
return Flow.fromSinkAndSource(in, out);
});
}

并且WebSocket可以保存在服务器端。

  1. 但是我如何通过WebSocket发送数据?(已触发服务器端(

这在2.5中很容易做到,但文档对Play 2.6没有太大帮助。

在Akka actors的帮助下,我成功地实现了websocket。在第一步中,定义将处理消息的参与者

public class WebSocketActor extends AbstractActor {
private final ActorRef out;
@Inject
public WebSocketActor(ActorRef out) {
this.out = out;
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, message ->
out.tell("Sending message at " + LocalDateTime.now().toString(), self())
)
.build();
}
public static Props props(final ActorRef out) {
return Props.create(WebSocketActor.class, out);
}
}

将为每个客户端创建此参与者。ActorRef out将向连接的客户端发送消息。在本例中,在传递给WebSocketActor的每个字符串消息上向客户端发送响应。

现在定义API端点为客户端打开对websocket的访问。定义ActorFlow,它将在新连接上创建actor的新实例

public WebSocket ws() {
return WebSocket.Text.accept(request -> ActorFlow.actorRef((out) -> WebSocketActor.props(out), actorSystem, materializer));
}

根据源代码ActorFlow创建具有flowActor名称的演员。因此,要将消息发送到代码中某个位置的websocket,我们可以通过参与者的路径找到他们。这将向所有连接的客户端广播消息

actorSystem.actorSelection("/user/*/flowActor").tell("Hello", ActorRef.noSender());

不幸的是,我没有找到简单的方法来更改ActorFlow的默认名称,但也许这个答案可以帮助你玩scala-akka websockets更改actor路径。

您还可以从playframework示例中查看playjavawebsocket示例项目。

最新更新