Переменные пути в Spring Отображение WebSockets @SendTo

У меня есть, что я думаю, очень простое приложение Spring WebSocket. Тем не менее, я пытаюсь использовать переменные пути для подписки, а также отображение сообщений.

Я опубликовал приведенный ниже пример. Я ожидаю, что аннотация @SendTo вернется к подписчикам на основе их fleetId. т.е. от POST до /fleet/MyFleet/driver/MyDriver следует уведомлять подписчиков /fleet/MyFleet, но я не вижу этого поведения.

Стоит отметить, что работает подписка на литерал /fleet/{fleetId}. Это предназначено? Не хватает ли какой-то части конфигурации? Или это не так, как это работает?

Я еще не очень хорошо знаком с WebSockets или этим проектом Spring, поэтому заранее спасибо.

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

Отправить образец

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

Ответ 1

Даже если @MessageMapping поддерживает заполнители, они не отображаются/не разрешаются в @SendTo. В настоящее время нет способа определить динамические адресаты с аннотацией @SendTo (см. Вопрос SPR-12170). Вы могли бы использовать SimpMessagingTemplate пока что (так, как это работает внутри). Вот как вы это сделаете:

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

В вашем коде пункт назначения/тема/флот/{fleetId} 'рассматривается как литерал, что причина, по которой подписка на него работает, только потому, что вы отправляете в тот же пункт назначения.

Если вы просто хотите отправить некоторые исходные данные пользователя, вы можете вернуть его прямо в подписке:

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

Update: В Spring 4.2 поддерживаемые места назначения переменных поддерживаются, теперь можно сделать что-то вроде:

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