Spring WebSockets @SendTo映射中的路径变量

2022-08-31 17:28:30

我认为,我有一个非常简单的Spring WebSocket应用程序。但是,我正在尝试将路径变量用于订阅以及消息映射。

我在下面发布了一个转述的例子。我希望注释根据他们的.即,一个 to 应该通知订阅者,但我没有看到这种行为。@SendTofleetIdPOST/fleet/MyFleet/driver/MyDriver/fleet/MyFleet

值得注意的是,订阅文字是有效的。这是故意的吗?我是否缺少某些配置?或者这不是它的工作方式吗?/fleet/{fleetId}

我对WebSockets或这个春季项目还不是很熟悉,所以提前感谢。

控制器.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();
    }
}

索引.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

即使支持占位符,它们也不会在目标中公开/解析。目前,无法使用注释定义动态目标(请参阅问题 SPR-12170)。您可以暂时使用(无论如何,这就是它在内部的工作方式)。以下是操作方法:@MessageMapping@SendTo@SendToSimpMessagingTemplate

@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

您可以在路径内发送变量。例如,我发送“este/es/el/chat/java/”,并在服务器中作为“este:es:el:chat:java:"

客户:

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

服务器:

@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("/",":");

推荐