복붙노트

[SPRING] Spring WebSockets의 경로 변수 @SendTo 매핑

SPRING

Spring WebSockets의 경로 변수 @SendTo 매핑

내가 생각하기에, 아주 간단한 Spring WebSocket 애플리케이션이있다. 그러나 메시지 매핑뿐만 아니라 구독에 대한 경로 변수를 사용하려고합니다.

아래에 예를 들어 보았습니다. @SendTo 주석은 fleetId를 기반으로 가입자에게 다시 반환 될 것으로 기대합니다. 즉, / 함대 / MyFleet / driver / MyDriver에 대한 POST는 / fleet / MyFleet의 가입자에게 알려야하지만이 동작은 보이지 않습니다.

리터럴 / fleet / {fleetId}에 가입하는 것은 주목할 가치가 있습니다. 이것은 의도 된 것입니까? 구성의 일부가 누락 되었습니까? 아니면 이것이 작동 방식이 아닌가?

WebSocket이나 이번 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. ==============================

    1.@MessageMapping은 자리 표시자를 지원하지만 @SendTo 대상에서 노출 / 해결되지 않습니다. 현재 @SendTo 주석으로 동적 대상을 정의 할 수있는 방법은 없습니다 (SPR-12170 문제 참조). 당분간 SimpMessagingTemplate을 사용할 수 있습니다 (이것이 어쨌든 내부적으로 작동하는 방식입니다). 방법은 다음과 같습니다.

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

    코드에서 목적지 '/ topic / fleet / {fleetId}'는 리터럴로 취급됩니다. 정확히 동일한 목적지에 보내고 있기 때문에 그것이 구독하는 이유입니다.

    초기 사용자 특정 데이터를 보내려는 경우 구독에서 직접 반환 할 수 있습니다.

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

    최신 정보: 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);
    }
    
  2. from https://stackoverflow.com/questions/27047310/path-variables-in-spring-websockets-sendto-mapping by cc-by-sa and MIT license