使用 play framework 2.6 创建 websocket

Create websocket with play framework 2.6

我正在尝试使用 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可以保存在服务器端。

2) 但是我怎样才能通过 websocket 发送数据呢? (触发服务器端)

这在 2.5 中很容易做到,但文档对于播放 2.6 不是很有帮助。

谢谢

我在 Akka actors 的帮助下成功实现了 websocket。第一步定义将处理消息的 actor

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 的访问。定义将在新连接上创建新的 actor 实例的 ActorFlow

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

根据source code ActorFlow creates actors with flowActor name. So to send message to websockets somewhere in the code we can find actors by their path。这将向所有连接的客户端广播消息

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

不幸的是,我没有找到更改 ActorFlow 默认名称的简单方法,但也许这个答案可能对您有所帮助 play-scala-akka-websockets-change-actor-path

您也可以从 playframework 示例中查看 play-java-websocket-example 项目。