Spring5のリアクティブWebSocket
1. 概要
この記事では、新しいSpring 5 WebSockets APIと、SpringWebFluxが提供するリアクティブ機能を使用した簡単な例を作成します。
WebSocketは、クライアントとサーバー間の全二重通信を可能にするよく知られたプロトコルであり、クライアントとサーバーが高頻度で低遅延でイベントを交換する必要があるWebアプリケーションで一般的に使用されます。
Spring Framework 5は、フレームワークでのWebSocketサポートを最新化し、この通信チャネルにリアクティブ機能を追加しました。
SpringWebFluxここで詳細を見つけることができます。
2. Mavenの依存関係
spring-boot-integrationおよびspring-boot-starter-webfluxのspring-boot-starters依存関係を使用します。現在で入手可能です。 X159X]Springマイルストーンリポジトリ。
この例では、利用可能な最新バージョンの2.0.0.M7を使用していますが、常にMavenリポジトリーで利用可能な最新バージョンを取得する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
3. SpringでのWebSocket構成
構成は非常に簡単です。WebSocketHandlerを挿入して、SpringWebSocketアプリケーションのソケットセッションを処理します。
@Autowired
private WebSocketHandler webSocketHandler;
さらに、リクエストとハンドラーオブジェクト間のマッピングを担当する HandlerMappingbeanアノテーション付きメソッドを作成しましょう。
@Bean
public HandlerMapping webSocketHandlerMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/event-emitter", webSocketHandler);
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setOrder(1);
handlerMapping.setUrlMap(map);
return handlerMapping;
}
接続できるURLは次のとおりです。 ws:// localhost:
4. SpringでのWebSocketメッセージ処理
ReactiveWebSocketHandler クラスは、サーバー側でWebSocketセッションを管理する役割を果たします。
WebSocketHandler インターフェースを実装しているため、WebSocketクライアントにメッセージを送信するために使用されるhandleメソッドをオーバーライドできます。
@Component
public class ReactiveWebSocketHandler implements WebSocketHandler {
// private fields ...
@Override
public Mono<Void> handle(WebSocketSession webSocketSession) {
return webSocketSession.send(intervalFlux
.map(webSocketSession::textMessage))
.and(webSocketSession.receive()
.map(WebSocketMessage::getPayloadAsText)
.log());
}
}
5. シンプルなリアクティブWebSocketクライアントの作成
次に、WebSocketサーバーに接続して情報を交換できるSpringReactiveWebSocketクライアントを作成しましょう。
5.1. Mavenの依存関係
まず、Mavenの依存関係。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
ここでは、リアクティブWebSocketサーバーアプリケーションをセットアップするために以前に使用したものと同じspring-boot-starter-webfluxを使用しています。
5.2. WebSocketクライアント
それでは、サーバーとの通信を開始するReactionClientWebSocketクラスを作成しましょう。
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 を使用していることがわかります。これは、ReactorNettyで使用するWebSocketClient実装です。
さらに、クライアントはURL ws:// localhost:8080 / event-emitter、を介してWebSocketサーバーに接続し、サーバーに接続するとすぐにセッションを確立します。
また、接続要求とともにサーバーにメッセージ( “ event-spring-reactive-client-websocket “)を送信していることもわかります。
さらに、この方法送信が呼び出され、パラメータとしてタイプの変数を期待します出版社
さらに、タイプ StringのFluxを期待するthenMany(…)メソッドが呼び出されます。 receive()メソッドは、着信メッセージのフラックスを取得します。着信メッセージは後で文字列に変換されます。
最後に、 block()メソッドは、指定された時間(この例では10秒)後にクライアントをサーバーから強制的に切断します。
5.3. クライアントの起動
実行するには、ReactiveWebSocketサーバーが稼働していることを確認してください。 次に、 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サーバーアプリケーションを使用してみましょう。
<div class="events"></div>
<script>
var clientWebSocket = new WebSocket("ws://localhost:8080/event-emitter");
clientWebSocket.onopen = function() {
console.log("clientWebSocket.onopen", clientWebSocket);
console.log("clientWebSocket.readyState", "websocketstatus");
clientWebSocket.send("event-me-from-browser");
}
clientWebSocket.onclose = function(error) {
console.log("clientWebSocket.onclose", clientWebSocket, error);
events("Closing connection");
}
clientWebSocket.onerror = function(error) {
console.log("clientWebSocket.onerror", clientWebSocket, error);
events("An error occured");
}
clientWebSocket.onmessage = function(error) {
console.log("clientWebSocket.onmessage", clientWebSocket, error);
events(error.data);
}
function events(responseEvent) {
document.querySelector(".events").innerHTML += responseEvent + "<br>";
}
</script>
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フレームワークを使用して、サーバーとクライアント間のWebSocket通信を作成し、SpringWebfluxによって提供される新しいリアクティブ機能を実装する方法の例を示しました。
いつものように、完全な例はGitHubリポジトリにあります。