1. Обзор
В этом кратком руководстве мы проиллюстрируем, как отправить сообщение конкретному сеансу или конкретному пользователю с помощью Spring WebSockets .
Для ознакомления с вышеуказанным модулем, пожалуйста, обратитесь к этой статье .
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 , но для быстрого примера проще настроить импортированную конфигурацию.
В первом методе мы настроили простой брокер сообщений на основе памяти для передачи сообщений обратно клиенту в пункты назначения с префиксами “/тема” и “/очередь” .
И, во-вторых, мы зарегистрировали конечные точки stomp в “/приветствие” .
В случае, если мы хотим включить 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. Конечная точка WebSocket
Начиная с ВЫПУСКА Spring 5.0.5., нет необходимости делать какие-либо настройки из-за улучшения аннотации @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. Клиент 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 , указывающий на ” /приветствие ” для отображения в конфигурации WebSocket .
Когда мы подписываем клиента на ” /пользователь/очередь/ошибки ” и ” /пользователь/очередь/ответ “, мы используем отмеченную информацию из последнего раздела.
Как мы видим, @SendToUser указывает на ” очередь/ошибки “, но сообщение будет отправлено на ” /пользователь/очередь/ошибки “.
6. Заключение
В этой статье мы рассмотрели способ отправки сообщения непосредственно пользователю или идентификатору сеанса с помощью Spring WebSocket
Как всегда, полный исходный код примеров доступен на GitHub .