Spring 5のReactive WebSocket

Spring 5のリアクティブWebSocket

1. 概要

この記事では、新しいSpring Framework 5 WebSockets APIと、Spring WebFluxFrameworkが提供するリアクティブ機能を使用した簡単な例を作成します。

WebSocketは、クライアントとサーバー間の全二重通信を可能にするよく知られたプロトコルで、一般に、クライアントとサーバーが高頻度で低遅延でイベントを交換する必要があるWebアプリケーションで使用されます。

Spring Framework 5では、フレームワークでWebSocketのサポートが近代化されており、この通信チャネルに事後対応機能が追加されています。

Spring WebFluxhereで詳細を見つけることができます。

2. Mavenの依存関係

現在Spring Milestone Repositoryで利用可能なspring-boot-integrationspring-boot-starter-webfluxには、すぐに使用できるspring-boot-startersの依存関係を使用します。

この例では、利用可能な最新バージョンの2.0.0.M7を使用しています。


    org.springframework.boot
    spring-boot-starter-integration


    org.springframework.boot
    spring-boot-starter-webflux

3. SpringでのWebSocket構成

構成は非常に簡単です。SpringWebSocketアプリケーションでソケットセッションを処理するためにWebSocketHandlerを挿入します。

@Autowired
private WebSocketHandler webSocketHandler;

さらに、リクエストとハンドラオブジェクト間のマッピングを担当するHandlerMappingBeanアノテーション付きメソッドを作成しましょう。

@Bean
public HandlerMapping webSocketHandlerMapping() {
    Map map = new HashMap<>();
    map.put("/event-emitter", webSocketHandler);

    SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
    handlerMapping.setOrder(1);
    handlerMapping.setUrlMap(map);
    return handlerMapping;
}

ここで、使用可能なURLを確認できます:ws://localhost:<port>/event-emitter.

4. SpringでのWebSocketメッセージ処理

ReactiveWebSocketHandlerクラスは、サーバー側でWebSocketセッションを管理する役割を果たします。

WebSocketHandlerインターフェースを実装しているため、WebSocketクライアントにメッセージを送信するために使用されるhandleメソッドをオーバーライドできます。

@Component
public class ReactiveWebSocketHandler implements WebSocketHandler {

    // private fields ...

    @Override
    public Mono handle(WebSocketSession webSocketSession) {
        return webSocketSession.send(intervalFlux
          .map(webSocketSession::textMessage))
          .and(webSocketSession.receive()
            .map(WebSocketMessage::getPayloadAsText)
            .log());
    }
}

5. シンプルなリアクティブWebSocketクライアントの作成

次に、WebSocketサーバーに接続して情報を交換できるSpring ReactiveWebSocketクライアントを作成しましょう。

まず、Mavenの依存関係。


    org.springframework.boot
    spring-boot-starter-webflux

ここでは、リアクティブWebSocketサーバーアプリケーションをセットアップするために以前に使用したものと同じspring-boot-starter-webfluxを使用しています。

それでは、サーバーとの通信の開始を担当するReactiveClientWebSocketクラスを作成しましょう。

public class ReactiveJavaClientWebSocket {

    public static void main(String[] args) throws InterruptedException {

        WebSocketClient client = new ReactorNettyWebSocketClient();
        client.execute(
          URI.create("ws://localhost:8080/event-emitter"),
          session -> session.send(
            Mono.just(session.textMessage("event-spring-reactive-client-websocket")))
            .thenMany(session.receive()
              .map(WebSocketMessage::getPayloadAsText)
              .log())
            .then())
            .block(Duration.ofSeconds(10L));
    }
}

上記のコードでは、Reactor Nettyで使用するためのWebSocketClient実装であるReactorNettyWebSocketClientを使用していることがわかります。

さらに、URLws://localhost:8080/event-emitter,を介したWebSocketサーバーへのクライアント接続は、サーバーに接続されるとすぐにセッションを確立します。

また、接続要求とともにサーバーにメッセージ(“event-spring-reactive-client-websocket“)を送信していることもわかります。

さらに、メソッドsendが呼び出され、パラメーターとしてタイプPublisher<T>,の変数が期待されます。この場合、Publisher<T>Mono<T>であり、Tは単純です。文字列「event-me-from-reactive-java-client-websocket」。

さらに、タイプStringFluxを予期するthenMany(…)メソッドが呼び出されます。 receive()メソッドは、受信メッセージのフラックスを取得します。これは後で文字列に変換されます。

最後に、block()メソッドは、指定された時間(この例では10秒)後にクライアントをサーバーから強制的に切断します。

実行するには、Reactive WebSocket Serverが稼働していることを確認してください。 次に、ReactiveJavaClientWebSocketクラスを起動すると、sysoutログで発行されているイベントを確認できます。

[reactor-http-nio-4] INFO reactor.Flux.Map.1 -
onNext({"eventId":"6042b94f-fd02-47a1-911d-dacf97f12ba6",
"eventDt":"2018-01-11T23:29:26.900"})

また、Reactive WebSocketサーバーのログで、接続試行中にクライアントから送信されたメッセージを確認できます。

[reactor-http-nio-2] reactor.Flux.Map.1:
onNext(event-me-from-reactive-java-client)

また、クライアントが要求を終了した後(この場合は10秒後に)、終了した接続のメッセージを確認できます。

[reactor-http-nio-2] reactor.Flux.Map.1: onComplete()

6. ブラウザWebSocketクライアントの作成

簡単なHTML / JavascriptクライアントWebSocketを作成して、リアクティブWebSocketサーバーアプリケーションを使用してみましょう。

WebSocketサーバーを実行し、このHTMLファイルをブラウザー(Chrome、Internet Explorer、Mozilla Firefoxなど)で開くと、画面にイベントが1秒遅れて印刷され、画面に印刷されるはずです。 WebSocketサーバー。

{"eventId":"c25975de-6775-4b0b-b974-b396847878e6","eventDt":"2018-01-11T23:56:09.780"}
{"eventId":"ac74170b-1f71-49d3-8737-b3f9a8a352f9","eventDt":"2018-01-11T23:56:09.781"}
{"eventId":"40d8f305-f252-4c14-86d7-ed134d3e10c6","eventDt":"2018-01-11T23:56:09.782"}

7. 結論

ここでは、Spring 5 Frameworkを使用して、サーバーとクライアント間のWebSocket通信を作成し、SpringWebfluxによって提供される新しいリアクティブ機能を実装する方法の例を示しました。

いつものように、完全な例はGitHub repositoryにあります。