1. 概要

このクイックチュートリアルでは、 SpringWebSocketsを使用して特定のセッションまたは特定のユーザーにメッセージを送信する方法を説明します。

上記のモジュールの概要については、この記事を参照してください。

2. WebSocketの構成

まず、メッセージブローカーとWebSocketアプリケーションエンドポイント構成する必要があります。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig
  extends AbstractWebSocketMessageBrokerConfigurer {
	
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic/", "/queue/");
	config.setApplicationDestinationPrefixes("/app");
    }
	 
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
	registry.addEndpoint("/greeting");
    }	
}

@EnableWebSocketMessageBroker 私たちを使用してWebSocketを介したブローカー支援メッセージングを有効にしました STOMP、 の略ですストリーミングテキスト指向のメッセージングプロトコル。 このアノテーションは@Configurationと組み合わせて使用する必要があることに注意してください。 

AbstractWebSocketMessageBrokerConfigurer を拡張することは必須ではありませんが、簡単な例として、インポートされた構成をカスタマイズする方が簡単です。

最初の方法では、「/topic」および「/queue」のプレフィックスが付いた宛先でメッセージをクライアントに戻すために、単純なメモリベースのメッセージブローカーを設定しました。

そして、2番目に、「/greeting」にストンプエンドポイントを登録しました。

SockJSを有効にする場合は、レジスタ部分を修正する必要があります。

registry.addEndpoint("/greeting").withSockJS();

3. インターセプターによるセッションIDの取得

セッションIDを取得する1つの方法は、ハンドシェイク中にトリガーされ、要求データから情報を取得するSpringInterceptorを追加することです。

このインターセプターは、 WebSocketConfig:に直接追加できます。

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
        
registry
  .addEndpoint("/greeting")
  .setHandshakeHandler(new DefaultHandshakeHandler() {

      public boolean beforeHandshake(
        ServerHttpRequest request, 
        ServerHttpResponse response, 
        WebSocketHandler wsHandler,
        Map attributes) throws Exception {
 
            if (request instanceof ServletServerHttpRequest) {
                ServletServerHttpRequest servletRequest
                 = (ServletServerHttpRequest) request;
                HttpSession session = servletRequest
                  .getServletRequest().getSession();
                attributes.put("sessionId", session.getId());
            }
                return true;
        }}).withSockJS();
    }

4. WebSocketエンドポイント

Spring 5.0.5.RELEASE以降、 @SendToUserアノテーションが改善され、「を介してユーザーの宛先にメッセージを送信できるようになったため、カスタマイズを行う必要がなくなりました。 ] / user /{sessionId}/…」ではなく「/user /{user}/…」。

つまり、アノテーションは入力メッセージのセッションIDに依存して機能し、セッション専用の宛先に効果的に応答を送信します。

@Controller
public class WebSocketController {

    @Autowired
    private SimpMessageSendingOperations messagingTemplate;

    private Gson gson = new Gson();
 
    @MessageMapping("/message")
    @SendToUser("/queue/reply")
    public String processMessageFromClient(
      @Payload String message, 
      Principal principal) throws Exception {
	return gson
          .fromJson(message, Map.class)
          .get("name").toString();
    }
	
    @MessageExceptionHandler
    @SendToUser("/queue/errors")
    public String handleException(Throwable exception) {
        return exception.getMessage();
    }
}

@SendToUser は、メッセージ処理メソッドの戻り値をメッセージとして指定された宛先に「 / user / {username}“

5. WebSocketクライアント

function connect() {
    var socket = new WebSocket('ws://localhost:8080/greeting');
    ws = Stomp.over(socket);

    ws.connect({}, function(frame) {
        ws.subscribe("/user/queue/errors", function(message) {
            alert("Error " + message.body);
        });

        ws.subscribe("/user/queue/reply", function(message) {
            alert("Message " + message.body);
        });
    }, function(error) {
        alert("STOMP error " + error);
    });
}

function disconnect() {
    if (ws != null) {
        ws.close();
    }
    setConnected(false);
    console.log("Disconnected");
}

WebSocketConfigurationのマッピング用に「/greeting」を指す新しいWebSocketが作成されます。

クライアントを「/user / queue / errors 」にサブスクライブする場合、「 / user / queue / reply 」では、前のセクションのコメント情報を使用します。

ご覧のとおり、@SendToUserは「queue/ errors 」を指していますが、メッセージは「 / user / queue /errors」に送信されます。

6. 結論

この記事では、SpringWebSocketを使用してユーザーまたはセッションIDに直接メッセージを送信する方法を検討しました。

いつものように、例の完全なソースコードは、GitHubから入手できます。