web-dev-qa-db-fra.com

Variables de chemin d'accès dans le mappage Spring WebSockets @SendTo

Ce que je pense être une application Spring WebSocket très simple. Cependant, j'essaie d'utiliser des variables de chemin d'accès pour l'abonnement ainsi que le mappage des messages.

J'ai posté un exemple paraphrasé ci-dessous. Je m'attendrais à ce que l'annotation @SendTo soit renvoyée aux abonnés en fonction de leur fleetId. C'est-à-dire qu'une POST à /fleet/MyFleet/driver/MyDriver devrait notifier les abonnés de /fleet/MyFleet, mais je ne vois pas ce comportement.

Il est intéressant de noter que s’abonner au /fleet/{fleetId} littéral fonctionne. Est-ce prévu? Est-ce qu'il me manque un morceau de configuration? Ou est-ce simplement pas comment ça marche?

Je ne connais pas encore très bien WebSockets ou ce projet Spring, merci d'avance.

Controller.Java

...
@MessageMapping("/fleet/{fleetId}/driver/{driverId}")
@SendTo("/topic/fleet/{fleetId}")
public Simple simple(@DestinationVariable String fleetId, @DestinationVariable String driverId) {
    return new Simple(fleetId, driverId);
}
...

WebSocketConfig.Java

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/live");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/fleet").withSockJS();
    }
}

index.html

var socket = new SockJS('/fleet');
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
    // Doesn't Work
    stompClient.subscribe('/topic/fleet/MyFleet', function(greeting) {
    // Works
    stompClient.subscribe('/topic/fleet/{fleetId}', function(greeting) {
        // Do some stuff
    });
});

Envoyer un échantillon

    stompClient.send("/live/fleet/MyFleet/driver/MyDriver", {}, JSON.stringify({
        // Some simple content
    }));
34
bvulaj

Même si @MessageMapping prend en charge les espaces réservés, ils ne sont pas exposés/résolus dans les destinations @SendTo. Actuellement, il est impossible de définir des destinations dynamiques avec l'annotation @SendTo (voir le numéro SPR-12170 ). Vous pouvez utiliser la SimpMessagingTemplate pour le moment (c'est comme ça que ça fonctionne en interne de toute façon). Voici comment vous le feriez:

@MessageMapping("/fleet/{fleetId}/driver/{driverId}")
public void simple(@DestinationVariable String fleetId, @DestinationVariable String driverId) {
    simpMessagingTemplate.convertAndSend("/topic/fleet/" + fleetId, new Simple(fleetId, driverId));
}

Dans votre code, la destination '/topic/flotte/{flotteId}' est traitée comme un littéral, c'est pourquoi son abonnement fonctionne, simplement parce que vous envoyez la même destination.

Si vous souhaitez simplement envoyer des données initiales spécifiques à l'utilisateur, vous pouvez les renvoyer directement dans l'abonnement:

@SubscribeMapping("/fleet/{fleetId}/driver/{driverId}")
public Simple simple(@DestinationVariable String fleetId, @DestinationVariable String driverId) {
    return new Simple(fleetId, driverId);
}

Update: Dans Spring 4.2, les espaces réservés des variables de destination sont pris en charge. Il est maintenant possible de faire quelque chose comme:

@MessageMapping("/fleet/{fleetId}/driver/{driverId}")
@SendTo("/topic/fleet/{fleetId}")
public Simple simple(@DestinationVariable String fleetId, @DestinationVariable String driverId) {
    return new Simple(fleetId, driverId);
}
81
Sergi Almar

vous pouvez envoyer une variable à l'intérieur du chemin. par exemple, je vous envoie "este/es/el/chat/Java /" et vous obtenez le serveur comme "este: es: el: chat: Java: "

client:

stompSession.send("/app/chat/este/es/el/chat/Java/*", ...);

serveur:

@MessageMapping("/chat/**")
@SendToUser("/queue/reply")
public WebsocketData greeting(Message m,HelloMessage message,@Header("simpSessionId") String sessionId) throws Exception {
    Map<String, LinkedList<String>> nativeHeaders = (Map<String, LinkedList<String>>) m.getHeaders().get("nativeHeaders");
    String value= nativeHeaders.get("destination").getFirst().replaceAll("/app/chat/","").replaceAll("/",":");
0
ivan rc