Быстрый пример аннотации @SendToUser Spring Websockets

Быстрый пример аннотации @SendToUser Spring Websockets

1. обзор

В этом кратком руководстве мы проиллюстрируемhow to send a message to a specific session or particular user using Spring WebSockets.

Для введения в вышеуказанный модуль, пожалуйста, обратитесь кto this article.

2. Конфигурация WebSocket

Прежде всего нам нужноconfigure our message broker and WebSocket application endpoint:

@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 мыenabled a broker-backed messaging over WebSocket using*STOMP*,, что означаетStreaming Text Oriented Messaging Protocol. It’s important to remark that this annotation needs to be used in conjunction with the @Configuration

РасширятьAbstractWebSocketMessageBrokerConfigurer не обязательно, но для быстрого примера проще настроить импортированную конфигурацию.

В первом методе мы настраиваем простой брокер сообщений на основе памяти, чтобы передавать сообщения обратно клиенту в пункты назначения с префиксом“/topic” и“/queue”.

А во втором мы зарегистрировали конечные точки удара в“/greeting”.

В случае, если мы хотим включить SockJS, мы должны изменить часть регистра:

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

3. Получить идентификатор сессии по перехватчику

Один из способовto obtain the session id - добавить Spring Interceptor, который будет срабатывать во время рукопожатия и получать информацию из данных запроса.

Этот перехватчик можно добавить прямо в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 annotation, that allows us to send a message to a user destination с помощью «/user/{sessionId}/…», а не «/user/{user}/…».

Это означает, что аннотация работает, полагаясь на идентификатор сеанса входного сообщения, фактически отправляя ответ на пункт назначения, частный для сеанса:

@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 указывает, что возвращаемое значение метода обработки сообщений должно быть отправлено какMessage на указанныйdestination(s) prepended with “/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");
}

Создается новыйWebSocket, указывающий на «/greeting» для отображения вWebSocketConfiguration.

Когда мы подписываем клиента на «/user/queue/errors» и «/user/queue/reply», мы используем отмеченную информацию из последнего раздела.

Как мы видим,@SendToUser указывает на «queue/errors», но сообщение будет отправлено на «/user/queue/errors».

6. Заключение

В этой статье мы исследовали способ отправки сообщения непосредственно пользователю или идентификатору сеанса с помощью Spring WebSocket.

Как всегда, доступен полный исходный код примеровover on GitHub.