Springbootシリーズ記事の統合WebSocketによるブロードキャストメッセージプッシュ
18279 ワード
前言
springbootがwebsocketを統合する前に、websocketの基本概念と、それに関連するsockjs、stompが何なのかを簡単に説明します.
WebSocketの概要
WebSocketプロトコルは、HTML 5に新たに追加された単一TCP接続上でフルデュプレクス通信を行うプロトコルであり、WebSocket APIではブラウザとサーバが握手の動作をするだけで、ブラウザとサーバの間に高速チャネルが形成され、両者の間にデータが直接転送される.
WebSocketとHTTPの違いは、
WebSocketはフルデュプレクス通信プロトコルで、接続が確立されると、WebSocketサーバとブラウザ側がSocketのように積極的に相手にメッセージを送信することができます.HTTPはクライアントからのみ要求を開始し、サーバはクエリー結果を返し、サーバがクライアントに要求を自発的に送信することはできない.下図のように
WebSocketの特徴
ここでWebSocketの特徴をまとめます:-WebSocketサーバーとブラウザはすべて自発的に相手にメッセージを送ることができます-TCPプロトコルの上で創立して、サーバーの実現は比較的に容易です-HTTPプロトコルと良好な互換性を持って、デフォルトのポートも80と443で、しかも握手の段階はHTTPプロトコルを採用して、HTTPエージェント-データフォーマットを通じて比較的に軽くて、性能のオーバーヘッドは小さくて、通信効率-テキストを送信することもできるし、バイナリデータを送信することもできる-同源制限はなく、クライアントは任意のサーバと通信することができる-プロトコル識別子は
SockJS
SockJSはブラウザ上で実行されるJavaScriptライブラリであり、ブラウザがWebSocketをサポートしていない場合、このライブラリはWebSocketのサポートをシミュレートすることができ、ブラウザとWebサーバ間の低遅延、全二重、ドメイン間の通信チャネルを実現する.
STOMP
STOMP(STOMP)すなわちSimple(or Streaming)Text Oriented Messaging Protocolの略称である単純(ストリーム)テキスト指向メッセージプロトコルは、STOMPクライアントが任意のSTOMPメッセージエージェント(Broker)と対話できるように、ユーザ操作可能な接続フォーマットを提供し、STOMPプロトコルは設計が簡単で、クライアントの開発が容易であるため、多くの言語と多くのプラットフォームで広く応用されている.
以前の紹介ではWebSocketはTCPプロトコルに基づいていると述べていましたが、WebSocket(またはSockJS)を直接使用してプログラミングするのはTCPソケットを直接使用してWebアプリケーションをプログラミングするのと似ています.これは非常につらいです.上層プロトコルがないため、アプリケーション間で送信される消息の意味を定義する必要があります.また、接続の両端がこれらの意味に従うことを確保する必要があります.
STOMPは、HTTPがTCPソケットに要求応答モデル層を追加するのと同様に、WebSocketの上にフレームベースの回線フォーマット層を提供し、メッセージの意味を定義するために使用される.
STOMPフレーム
STOMPフレームは、コマンド、1つまたは複数のヘッダメッセージ、および負荷からなり、以下に示すようにデータを送信するSTOMPフレームである.
以下のように分析します.-SEND:STOMPコマンドは、いくつかのコンテンツ-destination:ヘッダメッセージが送信されることを示します.メッセージがどこに送信されるかを示すために使用されます.content-length:ヘッダ情報は、負荷コンテンツのサイズ-空行-フレームコンテンツ(負荷)コンテンツを表すために使用されます.
WebSocket、SockJS、STOMPの関係
簡単に言えば、WebSocketはTCPベースの下位プロトコルであり、SockJSはWebSocketの代替案であり、WebSocketをサポートしないブラウザに用いられ、下位プロトコルでもあるが、STOMPはWebSocketの上位プロトコルであり、高級プロトコルである
SpringBoot統合WebSocket
前にいくつかの基礎知識を敷き詰めた後、次はこの文章のテーマに入って、SpringBoot+WebSocket+SockJS+STOMPを使ってラジオ式のWebSocketを構築します.
依存のインポート
WebSocket構成
上記のプログラムを解析する:-
下図はspring-websocketの公式ドキュメントから来て、websocketの通信モデル図として表します
モデル図を解読します.
同じターゲット:/aの場合、その接頭辞はメッセージの処理方法を決定し、2つに分けられる:
リクエストメッセージクラス
レスポンスメッセージクラス
クライアントからのSTOMPメッセージの処理
@MessageMapping注記を使用して、STOMPメッセージをコントローラで処理します.コードは次のとおりです.
コード解析:-handleメソッドは、クライアントが宛先
注釈の購読@SubcribeMapping
クライアントがアドレスを購読する場合、
ここでの注記@SubcribeMapping注記は、クライアントが
SimpMessagingTemplateの利用
SimpMessagingTemplate,SpringのSimpMessagingTemplateを使用すると、アプリケーションのどこでもメッセージを送信することができ、最初にメッセージを受信する必要もありません.
クライアント
クライアント作成にはstompを追加する必要がある.jsとsock.js、次は特定のクライアントコードです.
テスト結果
ページで接続をクリックすると、
参考資料&お礼 WebSocketチュートリアル スプリング実戦第4版 SpringBootシリーズ-統合WebSocketリアルタイム通信
springbootがwebsocketを統合する前に、websocketの基本概念と、それに関連するsockjs、stompが何なのかを簡単に説明します.
WebSocketの概要
WebSocketプロトコルは、HTML 5に新たに追加された単一TCP接続上でフルデュプレクス通信を行うプロトコルであり、WebSocket APIではブラウザとサーバが握手の動作をするだけで、ブラウザとサーバの間に高速チャネルが形成され、両者の間にデータが直接転送される.
WebSocketとHTTPの違いは、
WebSocketはフルデュプレクス通信プロトコルで、接続が確立されると、WebSocketサーバとブラウザ側がSocketのように積極的に相手にメッセージを送信することができます.HTTPはクライアントからのみ要求を開始し、サーバはクエリー結果を返し、サーバがクライアントに要求を自発的に送信することはできない.下図のように
WebSocketの特徴
ここでWebSocketの特徴をまとめます:-WebSocketサーバーとブラウザはすべて自発的に相手にメッセージを送ることができます-TCPプロトコルの上で創立して、サーバーの実現は比較的に容易です-HTTPプロトコルと良好な互換性を持って、デフォルトのポートも80と443で、しかも握手の段階はHTTPプロトコルを採用して、HTTPエージェント-データフォーマットを通じて比較的に軽くて、性能のオーバーヘッドは小さくて、通信効率-テキストを送信することもできるし、バイナリデータを送信することもできる-同源制限はなく、クライアントは任意のサーバと通信することができる-プロトコル識別子は
ws
(暗号化されている場合はwss
)、サーバURLはURLであるSockJS
SockJSはブラウザ上で実行されるJavaScriptライブラリであり、ブラウザがWebSocketをサポートしていない場合、このライブラリはWebSocketのサポートをシミュレートすることができ、ブラウザとWebサーバ間の低遅延、全二重、ドメイン間の通信チャネルを実現する.
STOMP
STOMP(STOMP)すなわちSimple(or Streaming)Text Oriented Messaging Protocolの略称である単純(ストリーム)テキスト指向メッセージプロトコルは、STOMPクライアントが任意のSTOMPメッセージエージェント(Broker)と対話できるように、ユーザ操作可能な接続フォーマットを提供し、STOMPプロトコルは設計が簡単で、クライアントの開発が容易であるため、多くの言語と多くのプラットフォームで広く応用されている.
以前の紹介ではWebSocketはTCPプロトコルに基づいていると述べていましたが、WebSocket(またはSockJS)を直接使用してプログラミングするのはTCPソケットを直接使用してWebアプリケーションをプログラミングするのと似ています.これは非常につらいです.上層プロトコルがないため、アプリケーション間で送信される消息の意味を定義する必要があります.また、接続の両端がこれらの意味に従うことを確保する必要があります.
STOMPは、HTTPがTCPソケットに要求応答モデル層を追加するのと同様に、WebSocketの上にフレームベースの回線フォーマット層を提供し、メッセージの意味を定義するために使用される.
STOMPフレーム
STOMPフレームは、コマンド、1つまたは複数のヘッダメッセージ、および負荷からなり、以下に示すようにデータを送信するSTOMPフレームである.
SEND
destination:/app/room-message
content-length:20
{\"message\":\"Hello!\"}
以下のように分析します.-SEND:STOMPコマンドは、いくつかのコンテンツ-destination:ヘッダメッセージが送信されることを示します.メッセージがどこに送信されるかを示すために使用されます.content-length:ヘッダ情報は、負荷コンテンツのサイズ-空行-フレームコンテンツ(負荷)コンテンツを表すために使用されます.
WebSocket、SockJS、STOMPの関係
簡単に言えば、WebSocketはTCPベースの下位プロトコルであり、SockJSはWebSocketの代替案であり、WebSocketをサポートしないブラウザに用いられ、下位プロトコルでもあるが、STOMPはWebSocketの上位プロトコルであり、高級プロトコルである
SpringBoot統合WebSocket
前にいくつかの基礎知識を敷き詰めた後、次はこの文章のテーマに入って、SpringBoot+WebSocket+SockJS+STOMPを使ってラジオ式のWebSocketを構築します.
依存のインポート
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-websocketartifactId>
dependency>
WebSocket構成
@Configuration
@EnableWebSocketMessageBroker // STOMP
public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// STOMP , WebSocket WebSocket
// , ,
registry.addEndpoint("/point")
//
.setAllowedOrigins("*")
// SockJS
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// , "/topic","/queue" STOMP
registry.enableSimpleBroker("/topic", "/queue");
// "/app", @MessageMapping
registry.setApplicationDestinationPrefixes("/app");
}
}
上記のプログラムを解析する:-
@EnableWebSocketMessageBroker
注記WebSocketだけでなく、エージェントベースのSTOMPメッセージ-registerStompEndpoints
をリロードする方法も構成されており、"/point"をSTOMPエンドポイントとして登録するには、クライアントが先にこのエンドポイント-リロードconfigureMessageBroker
に接続してメッセージエージェントを構成するとともに、アプリケーションの宛先プレフィックスを設定する必要がある.アプリケーションを宛先とするメッセージが@MessageMapoping
注釈付きコントローラメソッドに直接ルーティングされる場合下図はspring-websocketの公式ドキュメントから来て、websocketの通信モデル図として表します
モデル図を解読します.
同じターゲット:/aの場合、その接頭辞はメッセージの処理方法を決定し、2つに分けられる:
/app/a
と/topic/a
、/topic/a
であれば、メッセージボディを単純なエージェントメッセージプロセッサに直接送信することができ、/app/a
であれば、アプリケーション内の@MessageMapping
注釈を有するコントローラメソッドにメッセージをルーティングする.コントローラ・メソッドで処理を行い、その後、処理結果をbrokeChannel
に送信し、最後に単純エージェント・メッセージ・プロセッサにメッセージを送信し、両方の場合、最後にエージェントを介してクライアントの宛先に再送信する.リクエストメッセージクラス
public class RequestMessage {
private String name;
public String getName() {
return name;
}
}
レスポンスメッセージクラス
public class ResponseMessage {
private String responseMessage;
public ResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
public ResponseMessage() {
}
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
}
クライアントからのSTOMPメッセージの処理
@MessageMapping注記を使用して、STOMPメッセージをコントローラで処理します.コードは次のとおりです.
@Controller
public class GreetingController {
/**
* /app/greeting
*
* @param greeting
* @return
*/
@MessageMapping("/greeting")
// @SendTo("/topic/say")
public ResponseMessage handle(RequestMessage greeting) {
//Spring STOMP RequestMessage
System.out.println(greeting.getName());
return new ResponseMessage("welcome," + greeting.getName());
}
}
コード解析:-handleメソッドは、クライアントが宛先
/app/greeting
に送信したメッセージを処理し、/app
は、構成クラスでアプリケーションの宛先接頭辞に設定されているため、隠されている.このメソッドにはRequestMessage
パラメータがある.実際にSpringはメッセージ変換器を用いてメッセージ負荷をRequestMessageオブジェクトに変換する-この方法はResponseMessage
エンティティを返し、Springはメッセージ変換器を用いてこの返されたResponseMessageオブジェクトをメッセージ負荷に変換する-デフォルトでは、メッセージを返す宛先とクライアントがメッセージを送信する宛先は/topic
を追加するだけで、もちろん@SendTo注釈を使用して、メッセージを返す宛先を再ロードすることもできます.注釈の購読@SubcribeMapping
クライアントがアドレスを購読する場合、
@SubcribeMapping
注釈を使用して、購読の応答としてメッセージを送信することもできます. @SubscribeMapping("/subscribe")
public ResponseMessage subscribe() {
ResponseMessage responseMessage = new ResponseMessage();
responseMessage.setResponseMessage(" ");
return responseMessage;
}
ここでの注記@SubcribeMapping注記は、クライアントが
/app/subscribe
(/appがアプリケーション宛先のプレフィックス)宛先を購読すると、subscribe()メソッドが呼び出され、ResponseMessageオブジェクトが返されることを示しているSimpMessagingTemplateの利用
SimpMessagingTemplate,SpringのSimpMessagingTemplateを使用すると、アプリケーションのどこでもメッセージを送信することができ、最初にメッセージを受信する必要もありません.
クライアント
クライアント作成にはstompを追加する必要がある.jsとsock.js、次は特定のクライアントコードです.
<html>
<head>
<meta charset="UTF-8"/>
<title> WebSockettitle>
<script src="js/sockjs.min.js">script>
<script src="js/stomp.js">script>
<script src="js/jquery-3.1.1.js">script>
head>
<body onload="disconnect()">
<noscript><h2 style="color: #e80b0a;">Sorry, WebSocketh2>noscript>
<div>
<div>
<button id="connect" onclick="connect();"> button>
<button id="disconnect" disabled="disabled" onclick="disconnect();"> button>
div>
<div id="conversationDiv">
<label> label><input type="text" id="name"/>
<button id="sendName" onclick="sendName();"> button>
<p id="response">p>
<p id="callback">p>
div>
div>
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById("connect").disabled = connected;
document.getElementById("disconnect").disabled = !connected;
document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden';
$("#response").html();
$("#callback").html();
}
function connect() {
var socket = new SockJS('http://localhost:9999/point');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected:' + frame);
stompClient.subscribe('/topic/greeting', function (response) {
showResponse(JSON.parse(response.body).responseMessage);
});
stompClient.subscribe('/app/subscribe', function (response) {
showResponse(JSON.parse(response.body).responseMessage);
});
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log('Disconnected');
}
function sendName() {
var name = $('#name').val();
console.log('name:' + name);
stompClient.send("/app/greeting", {}, JSON.stringify({'name': name}));
}
function showResponse(message) {
$("#response").html(message);
}
function showCallback(message) {
$("#callback").html(message);
}
script>
body>
html>
テスト結果
ページで接続をクリックすると、
/point
のエンドポイントに接続し、/topic/greeting
と/app/subscribe
を同時に購読し、名前を入力して送信をクリックすると、/greeting
のURLにメッセージが送信され、サーバは/topic/greeting
にメッセージに応答します.参考資料&お礼