Um exemplo rápido da anotação @SendToUser do Spring Websockets '
1. Visão geral
Neste tutorial rápido, vamos ilustrarhow to send a message to a specific session or particular user using Spring WebSockets.
Para obter uma introdução ao módulo acima, consulteto this article.
2. Configuração WebSocket
Primeiro de tudo, precisamosconfigure 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");
}
}
Com@EnableWebSocketMessageBroker, nósenabled a broker-backed messaging over WebSocket using*STOMP*, que representaStreaming Text Oriented Messaging Protocol. It’s important to remark that this annotation needs to be used in conjunction with the @Configuration.
Não é obrigatório estender oAbstractWebSocketMessageBrokerConfigurer, mas, para um exemplo rápido, é mais fácil personalizar a configuração importada.
No primeiro método, configuramos um agente de mensagens simples baseado em memória para transportar as mensagens de volta para o cliente em destinos prefixados com“/topic”e“/queue”.
E, no segundo, registramos endpoints de stomp em“/greeting”.
Caso desejemos ativar o SockJS, precisamos alterar a parte do registro:
registry.addEndpoint("/greeting").withSockJS();
3. Obter ID da sessão pelo interceptador
Uma maneirato obtain the session id é adicionar um Spring Interceptor que será acionado durante o handshake e obterá as informações dos dados do pedido.
Este interceptor pode ser adicionado diretamente emWebSocketConfig:
@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. Ponto final WebSocket
A partir do Spring 5.0.5.RELEASE, não é necessário fazer nenhuma customização por causa da melhoria de@SendToUser annotation, that allows us to send a message to a user destination via “/user/{sessionId}/…” ao invés de “/user/{user}/…“.
Isso significa que a anotação funciona com base no ID da sessão da mensagem de entrada, enviando efetivamente uma resposta ao destino privado para a sessão:
@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();
}
}
É importante observar que@SendToUser indica que o valor de retorno de um método de tratamento de mensagem deve ser enviado comoMessage para odestination(s) prepended with “/user/{username}“ especificado.
5. Cliente 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");
}
Um novoWebSocket é criado apontando para “/greeting” para o mapeamento emWebSocketConfiguration.
Quando inscrevemos o cliente em “/user/queue/errors” e “/user/queue/reply” é onde usamos as informações comentadas da última seção.
Como podemos ver,@SendToUser aponta para “queue/errors” mas a mensagem será enviada para “/user/queue/errors“.
6. Conclusão
Neste artigo, exploramos uma maneira de enviar uma mensagem diretamente para um usuário ou id de sessão com Spring WebSocket
Como sempre, o código-fonte completo dos exemplos está disponívelover on GitHub.