2014-11-20 94 views
27

我有,我認爲是一個非常簡單的Spring WebSocket應用程序。但是,我試圖使用路徑變量進行訂閱以及消息映射。Spring WebSockets中的路徑變量@SendTo映射

我在下面發表了一個解釋性的例子。我期望@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 
    })); 

回答

63

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

更新: 在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); 
} 
+0

謝謝,@sergi!我希望能夠避開使用MessagingTempalte,但那也是一樣。使用'@ SubscribeMapping'和'@ SendTo'有什麼區別?前者是否跳過消息中介? – bvulaj 2014-11-21 14:17:42

+2

'@ SubscribeMapping'只攔截訂閱(不是消息到頻道),返回值將直接發送給用戶,但可以用'@ SendTo'覆蓋發送到另一個目的地(將被轉發到brokerChannel)。 '@ SendTo'也可以和'@ MessageMapping'一起使用來將響應發送到特定的目的地。所以基本上,'@ SendTo'可以和'@ MessageMapping'和'@ SubscribeMapping'一起使用。 – 2014-11-21 15:40:05

+0

我要做同樣的項目等於,但不能啓動,同樣的原型項目可以在github中使用。我知道工作春天但不工作WebSocket,我需要發送消息兩個人,並且消息同樣等於Skype。一對一,樹,如果邀請更多的用戶通訊 – 2016-12-15 18:11:01