Spring WebSockets:ユーザーチャットを構築する
1. 前書き
2. キュー、トピック、およびエンドポイント
Spring WebSocketとSTOMPを使用しているthree main ways to say where messages are sent and how they are subscribed toがあります。
-
Topics –任意のクライアントまたはユーザーに開かれた一般的な会話またはチャットトピック
-
Queues –特定のユーザーとその現在のセッション用に予約済み
-
Endpoints –一般的なエンドポイント
それでは、それぞれのコンテキストパスの例を簡単に見てみましょう。
-
“/topic/movies”
-
“/user/queue/specific-user”
-
“/secured/chat”
we must use queues to send messages to specific users, as topics and endpoints don’t support this functionalityに注意することが重要です。
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();
}
}
どのエンドポイントがシングルユーザー用に予約されるかを決定するので、ユーザーの宛先を必ず含めましょう。
また、すべてのキューとユーザーの宛先の前に“/secured”を付けて、認証が必要になるようにします。 保護されていないエンドポイントの場合、(他のセキュリティ設定の結果として)“/secured”プレフィックスを削除できます。
pom.xmlの観点からは、追加の依存関係は必要ありません。
4. URLマッピング
次のパターンに準拠するURLマッピングを使用して、クライアントにキューをサブスクライブさせます。
"/user/queue/updates"
このマッピングは、UserDestinationMessageHandlerによってユーザーセッション固有のアドレスに自動的に変換されます。
たとえば、“user123”という名前のユーザーがいる場合、対応するアドレスは次のようになります。
"/queue/updates-user123"
サーバー側では、次のURLマッピングパターンを使用してユーザー固有の応答を送信します。
"/user/{username}/queue/updates"
これも、すでにクライアント側にサブスクライブしている正しいURLマッピングに変換されます。
したがって、the essential ingredients here are two-fold:
-
指定したユーザー宛先プレフィックス(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
The @Header annotation allows access to headers exposed by the inbound message.たとえば、複雑なインターセプターを必要とせずに、現在のsessionIdを取得できます。 同様に、we can access the current user via Principal.
重要なのは、この記事で採用しているアプローチでは、URLマッピングに関して@sendToUserアノテーションをさらにカスタマイズできることです。 そのアノテーションの詳細については、thisのすばらしい記事をご覧ください。
クライアント側では、JavaScriptでconnect()をinitialize a SockJS instance and connect to our WebSocket server using STOMP:に使用します
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にアクセスし、それを「secured/room“ URLマッピング」に追加します。 This gives us the ability to dynamically and manually supply a user-specific subscription queue:
stompClient.subscribe('secured/user/queue/specific-user'
+ '-user' + that.sessionId, function (msgOut) {
//handle messages
}
すべての設定が完了すると、次のように表示されます。
そして、サーバーコンソールで:
6. 結論
このトピックの詳細については、公式のSpringblogとofficial documentationを確認してください。
いつものように、この記事で使用されているコードサンプルはover on GitHubで入手できます。