Java Spring WebSockets @SendTo 映射中的路径变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27047310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Path variables in Spring WebSockets @SendTo mapping
提问by bvulaj
I have, what I think to be, a very simple Spring WebSocket application. However, I'm trying to use path variables for the subscription as well as the message mapping.
我有一个非常简单的 Spring WebSocket 应用程序。但是,我正在尝试将路径变量用于订阅以及消息映射。
I've posted a paraphrased example below. I would expect the @SendTo
annotation to return back to the subscribers based on their fleetId
. ie, a POST
to /fleet/MyFleet/driver/MyDriver
should notify subscribers of /fleet/MyFleet
, but I'm not seeing this behavior.
我在下面发布了一个释义示例。我希望@SendTo
注释会根据订阅者的fleetId
. 即, a POST
to/fleet/MyFleet/driver/MyDriver
应该通知订阅者/fleet/MyFleet
,但我没有看到这种行为。
It's worth noting that subscribing to literal /fleet/{fleetId}
works. Is this intended? Am I missing some piece of configuration? Or is this just not how it works?
值得注意的是,订阅文字/fleet/{fleetId}
作品。这是故意的吗?我错过了一些配置吗?或者这不是它的工作原理?
I'm not very familiar with WebSockets or this Spring project yet, so thanks in advance.
我对 WebSockets 或这个 Spring 项目还不是很熟悉,所以提前致谢。
Controller.java
控制器.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
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
索引.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
});
});
Send Sample
发送样品
stompClient.send("/live/fleet/MyFleet/driver/MyDriver", {}, JSON.stringify({
// Some simple content
}));
采纳答案by Sergi Almar
Even though @MessageMapping
supports placeholders, they are not exposed / resolved in @SendTo
destinations. Currently, there's no way to define dynamic destinations with the @SendTo
annotation (see issue SPR-12170). You could use the SimpMessagingTemplate
for the time being (that's how it works internally anyway). Here's how you would do it:
即使@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));
}
In your code, the destination '/topic/fleet/{fleetId}' is treated as a literal, that's the reason why subscribing to it works, just because you are sending to the exact same destination.
在您的代码中,目的地 ' /topic/fleet/{fleetId}' 被视为文字,这就是订阅它的原因,因为您发送到完全相同的目的地。
If you just want to send some initial user specific data, you could return it directly in the subscription:
如果您只想发送一些初始用户特定数据,您可以直接在订阅中返回它:
@SubscribeMapping("/fleet/{fleetId}/driver/{driverId}")
public Simple simple(@DestinationVariable String fleetId, @DestinationVariable String driverId) {
return new Simple(fleetId, driverId);
}
Update:In Spring 4.2, destination variable placeholders are supported it's now possible to do something like:
更新:在 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);
}
回答by ivan rc
you can send a variable inside the path. for example i send "este/es/el/chat/java/" and obtaned in the server as "este:es:el:chat:java:"
您可以在路径内发送一个变量。例如,我发送“este/es/el/chat/java/ ”并在服务器中获得“este:es:el:chat:java:”
client:
客户:
stompSession.send("/app/chat/este/es/el/chat/java/*", ...);
server:
服务器:
@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("/",":");
回答by Jo?o Rodrigues
Actually I think this is what you might be looking for:
实际上,我认为这就是您可能正在寻找的内容:
@Autorwired
lateinit var template: SimpMessageTemplate;
@MessageMapping("/class/{id}")
@Throws(Exception::class)
fun onOffer(@DestinationVariable("id") id: String?, @Payload msg: Message) {
println("RECEIVED " + id)
template.convertAndSend("/topic/class/$id", Message("The response"))
}
Hope this helps someone! :)
希望这可以帮助某人!:)