我正在将 Spring Websocket 与 STOMP(简单消息代理)一起使用。在我的@Controller
我使用 method-level @SubscribeMapping
,它应该为客户端订阅一个主题,以便客户端随后接收该主题的消息。假设,客户端订阅了“聊天”主题:
stompClient.subscribe('/app/chat', ...);
由于客户端订阅了“/app/chat ”,而不是“/topic/chat”,因此该订阅将转到使用映射的方法@SubscribeMapping
:
@SubscribeMapping("/chat")
public List getChatInit() {
return Chat.getUsers();
}
这是 Spring 参考。说:
默认情况下,@SubscribeMapping 方法的返回值作为消息直接发送回连接的客户端,并且不通过代理。这对于实现请求-回复消息交互很有用;例如,在初始化应用程序 UI 时获取应用程序数据。
好的,这就是我想要的,但只是部分!订阅后发送一些初始化数据,好吧。但是订阅呢?在我看来,这里发生的事情只是一个request-reply,就像一个服务一样。订阅刚刚被消耗。如果是这种情况,请澄清我。
- 如果经纪人没有参与,客户是否订阅了某个地方?
- 如果稍后我想向“聊天”订阅者发送一些消息,客户端会收到吗?似乎并非如此。
- 谁真正意识到订阅?经纪人?还是其他人?
如果这里客户没有在任何地方订阅,我想知道为什么我们称之为“订阅”;因为客户端只收到一条消息,而不是未来的消息。
编辑:
为了确保订阅已经实现,我尝试如下:
服务器端:
配置:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
}
控制器:
@Controller
public class GreetingController {
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
System.out.println("inside greeting");
return new Greeting("Hello, " + message.getName() + "!");
}
@SubscribeMapping("/topic/greetings")
public Greeting try1() {
System.out.println("inside TRY 1");
return new Greeting("Hello, " + "TRY 1" + "!");
}
}
客户端:
...
stompClient.subscribe('/topic/greetings', function(greeting){
console.log('RECEIVED !!!');
});
stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
...
我想发生的事情:
- 当客户端订阅 '
/topic/greetings
' 时,该方法try1
被执行。 - 当客户端向'
/app/hello
'发送消息时,它应该收到问候消息,即@SendTo
'/topic/greetings
'。
结果:
如果客户端订阅
/topic/greetings
,则该方法try1
无法捕获它。当客户端发送 msg 到 '
/app/hello
' 时,greeting
方法被执行,并且客户端收到了问候消息。所以我们知道它已经/topic/greetings
正确地订阅了''。但请记住 1. 失败了。经过一番尝试,客户端订阅的时候已经可以了
'/app/topic/greetings'
,即前缀/app
(这个可以通过配置理解)。现在 1. 正在工作,但是这次 2. 失败:当客户端发送 msg 到 '
/app/hello
' 时,是的,greeting
方法已执行,但客户端没有收到问候消息。(因为可能现在客户端订阅了以 '/app
' 为前缀的主题,这是不需要的。)
所以,我得到的是我想要的 1 或 2 个,但不是这 2 个加在一起。
- 如何使用这种结构实现这一点(正确配置映射路径)?