Перейти к основному содержимому

Краткий пример использования аннотации @SendToUser в Spring Websockets

· 3 мин. чтения

1. Обзор

В этом кратком руководстве мы покажем, как отправить сообщение определенному сеансу или конкретному пользователю с помощью Spring WebSockets .

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

2. Конфигурация веб-сокета

Прежде всего, нам нужно настроить нашего брокера сообщений и конечную точку приложения 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» .

А во втором мы зарегистрировали конечные точки stomp в «/greeting» .

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

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

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

Один из способов получить идентификатор сеанса — добавить перехватчик Spring, который будет запускаться во время рукопожатия и получать информацию из данных запроса.

Этот перехватчик можно добавить прямо в 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. Конечная точка веб-сокета

Начиная с Spring 5.0.5.RELEASE нет необходимости выполнять какие-либо настройки из-за улучшения аннотации @SendToUser , которая позволяет нам отправлять сообщение пользователю через « /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 указывает, что возвращаемое значение метода обработки сообщений должно быть отправлено в виде сообщения в указанный пункт назначения с добавлением « /user/{username} « .

5. Веб-сокет-клиент

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.

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