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 .