Exemple rapide d’annotation @SendToUser de Spring Websockets

Exemple rapide d’annotation @SendToUser de Spring Websockets

1. Vue d'ensemble

Dans ce rapide didacticiel, nous allons illustrerhow to send a message to a specific session or particular user using Spring WebSockets.

Pour une introduction au module ci-dessus, veuillez vous référer àto this article.

2. Configuration WebSocket

Tout d'abord, nous devonsconfigure 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");
    }
}

Avec@EnableWebSocketMessageBroker nousenabled a broker-backed messaging over WebSocket using*STOMP*, qui représenteStreaming Text Oriented Messaging Protocol. It’s important to remark that this annotation needs to be used in conjunction with the @Configuration

Il n'est pas obligatoire d'étendre lesAbstractWebSocketMessageBrokerConfigurer mais, pour l'exemple rapide, il est plus facile de personnaliser la configuration importée.

Dans la première méthode, nous avons mis en place un courtier de messages basé sur la mémoire simple pour ramener les messages au client sur des destinations préfixées avec“/topic” et“/queue”.

Et, dans le second, nous avons enregistré des points de terminaison stomp à“/greeting”.

Si nous souhaitons activer SockJS, nous devons modifier la partie registre:

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

3. Obtenir l'identifiant de session par intercepteur

Une façonto obtain the session id est d'ajouter un Spring Interceptor qui se déclenchera pendant la négociation et obtiendra les informations à partir des données de la demande.

Cet intercepteur peut être ajouté directement enWebSocketConfig:

@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 Endpoint

À partir de Spring 5.0.5.RELEASE, aucune personnalisation n'est nécessaire en raison de l'amélioration de@SendToUser annotation, that allows us to send a message to a user destination via «/user/{sessionId}/…» plutôt que «/user/{user}/…».

Cela signifie que l'annotation fonctionne en fonction de l'ID de session du message d'entrée et envoie effectivement une réponse à la destination privée de la session:

@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();
    }
}

Il est important de noter que,@SendToUser indique que la valeur de retour d'une méthode de gestion des messages doit être envoyée sous forme deMessage auxdestination(s) prepended with “/user/{username} spécifiés.

5. WebSocket Client

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");
}

Un nouveauWebSocket est créé pointant vers «/greeting» pour le mappage enWebSocketConfiguration.

Lorsque nous souscrivons le client à «/user/queue/errors» et «/user/queue/reply», c'est là que nous utilisons les informations remarquées de la dernière section.

Comme nous pouvons le voir,@SendToUser pointe vers «queue/errors» mais le message sera envoyé vers «/user/queue/errors».

6. Conclusion

Dans cet article, nous avons exploré un moyen d'envoyer un message directement à un utilisateur ou à un identifiant de session avec Spring WebSocket

Comme toujours, le code source complet des exemples est disponibleover on GitHub.