Spring WebSockets:ユーザーチャットを構築する
1前書き
このチュートリアルでは、Spring WebSocketを使用して1人のユーザーにSTOMPメッセージを送信する方法について説明します。すべてのメッセージをすべてのユーザーにブロードキャストしたくない場合があるので、これは重要です。それに加えて、安全な方法でこれらのメッセージを送信する方法を説明します。
WebSocketの概要については、https://www.baeldung.com/websockets-spring[この]素晴らしいチュートリアルを参照してください。そして、セキュリティについてもっと深く掘り下げるには、https://www.baeldung.com/spring-security-websockets[この]記事をチェックして、WebSocketsの実装を保護してください。
2キュー、トピック、およびエンドポイント
Spring WebSocketsとSTOMPを使用して、メッセージがどこに送信され、どのように購読されるかを示すための3つの主な方法があります。
-
トピック
– 一般的な会話やチャットのトピックを任意のクライアントに公開したり、
ユーザー
。
キュー
– 特定のユーザーとその現在のセッション用に予約されています
-
エンドポイント
– 一般的なエンドポイント
それでは、それぞれのコンテキストパスの例を簡単に見てみましょう。
-
“/topic/movies”
-
“/user/queue/specific-user”
-
“/secure/chat”
トピックとエンドポイントはこの機能をサポートしていないため、
特定のユーザーにメッセージを送信するにはキューを使用する必要があることに注意することが重要です。
3構成
では、特定のユーザーにメッセージを送信できるようにアプリケーションを設定する方法を学びましょう。
public class SocketBrokerConfig extends
AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/secured/user/queue/specific-user");
config.setApplicationDestinationPrefixes("/spring-security-mvc-socket");
config.setUserDestinationPrefix("/secured/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/secured/room").withSockJS();
}
}
どのエンドポイントがシングルユーザー用に予約されているかが決定されるため、必ずユーザーの宛先を含めてください。
また、認証を要求するように、すべてのキューおよびユーザーの送信先に
“/secure”
を付けます。保護されていないエンドポイントでは、(他のセキュリティ設定の結果として)接頭辞
“/secure”
を削除できます。
pom.xml
の観点からは、追加の依存関係は必要ありません。
4 URLマッピング
次のパターンに準拠したURLマッピングを使用して、クライアントにキューへの登録を依頼します。
"/user/queue/updates"
このマッピングは
UserDestinationMessageHandler
によって自動的にユーザーセッション固有のアドレスに変換されます。
たとえば、
“ user123”
という名前のユーザーがいる場合、対応するアドレスは次のようになります。
"/queue/updates-user123"
サーバー側では、次のURLマッピングパターンを使用してユーザー固有のレスポンスを送信します。
"/user/{username}/queue/updates"
これも、クライアント側ですでに購読している正しいURLマッピングに変換されます。
このように、私たちは** ここでの本質的な成分は2つあります。
-
指定されたユーザー宛先プレフィックス(設定済み)を前に付ける
AbstractWebSocketMessageBrokerConfigurer
)にあります。
-
マッピング内のどこかで
“/queue”
を使用してください.
次のセクションでは、これを正確に行う方法を見ていきます。
5
convertAndSendToUser()
の呼び出し
SimpMessagingTemplate
または
SimpMessageSendingOperations
から
convertAndSendToUser()
を非静的に呼び出すことができます。
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/secured/room")
public void sendSpecific(
@Payload Message msg,
Principal user,
@Header("simpSessionId") String sessionId) throws Exception {
OutputMessage out = new OutputMessage(
msg.getFrom(),
msg.getText(),
new SimpleDateFormat("HH:mm").format(new Date()));
simpMessagingTemplate.convertAndSendToUser(
msg.getTo(), "/secured/user/queue/specific-user", out);
}
あなたは気づいたかもしれません:
@Header("simpSessionId") String sessionId
-
@ Header
アノテーションを使用すると、受信メッセージによって公開されているヘッダーにアクセスできます
たとえば、複雑なインターセプターを使用せずに現在の
sessionId
を取得できます。同様に、
Principal
。** を介して現在のユーザーにアクセスできます。
重要なことに、この記事で取り上げるアプローチは、URLマッピングに関して
@ sendToUser
アノテーションよりも優れたカスタマイズを提供します。その注釈の詳細については、https://www.baeldung.com/spring-websockets-sendtouser[この]素晴らしい記事をチェックしてください。
クライアントサイドでは、JavaScriptで
connect()
を使用してSockJSインスタンスを初期化し、STOMPを使用してWebSocketサーバーに接続します。
var socket = new SockJS('/secured/room');
var stompClient = Stomp.over(socket);
var sessionId = "";
stompClient.connect({}, function (frame) {
var url = stompClient.ws.__transport.url;
url = url.replace(
"ws://localhost:8080/spring-security-mvc-socket/secured/room/", "");
url = url.replace("/websocket", "");
url = url.replace(/^[0-9]+\//, "");
console.log("Your current session is: " + url);
sessionId = url;
}
また、提供された
sessionId
にアクセスし、それを「URLマッピング」に追加します。これにより、ユーザー固有のサブスクリプションキューを動的かつ手動で提供することができます。
stompClient.subscribe('secured/user/queue/specific-user'
+ '-user' + that.sessionId, function (msgOut) {
//handle messages
}
すべての設定が完了したら、次のようになります。
そして私たちのサーバーコンソールで:
6. 結論
公式のSpring
blog
およびhttps://docs.spring.io/spring-framework/docs/4.3.x/spring-framework-referenceを調べてください。このトピックに関する詳細は/html/websocket.html[公式のドキュメント]を参照してください。
いつものように、この記事で使われているコードサンプルはhttps://github.com/eugenp/tutorials/tree/master/spring-security-mvc-socket[GitHubで利用可能]です。