在客户端javascript上,我有
stomp.subscribe("/topic/path", function (message) {
console.info("message received");
});
在服务器端
public class Controller {
private final MessageSendingOperations<String> messagingTemplate;
@Autowired
public Controller(MessageSendingOperations<String> messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
@SubscribeMapping("/topic/path")
public void subscribe() {
LOGGER.info("before send");
messagingTemplate.convertAndSend(/topic/path, "msg");
}
}
从这个设置中,我偶尔(大约每30次页面刷新一次)会遇到消息丢失,这意味着我既看不到客户端的“message received”消息,也看不到Chrome调试工具的websocket流量。
“发送前”始终记录在服务器端。
这看起来像是当我在订阅()方法中调用MessageSending操作时,它还没有准备好。(如果我把Thread.sleep(50);在调用MessagingTemplate.convert和发送之前,问题会消失(或者不太可能重现))
我想知道以前是否有人经历过同样的情况,是否有事件可以告诉我MessageSendingOperations是否准备就绪。
有点晚了,但我想我应该加上我的解决方案。在通过消息传递模板发送数据之前,我遇到了订阅未注册的相同问题。这个问题很少发生,而且是不可预测的,因为与DefaultSub换算注册表
的竞争。
不幸的是,我不能仅仅使用@SubscriptionMapping
的返回方法,因为我们使用的是一个自定义对象映射器,它根据用户类型(本质上是属性过滤)进行动态更改。
我搜索了Spring代码,发现SubscriptionMethodReturnValueHandler负责发送订阅映射的返回值,并且与异步控制器的autowiredSimpMessageTemplate
不同的messagingTemplate!!
因此,解决方案是将MessageChannel clientOutboundChannel
自动连接到我的异步控制器中,并使用它创建SimpMessagingTemplate
。(您不能直接连接它,因为您只需将模板发送给代理即可)。
在订阅方法中,我使用直接模板,而在其他方法中,我使用到代理的模板。
这是我的解决方案。它是沿着同样的路线。添加了一个ExecutorChannelInterceptor
,并发布了一个自定义的SubcriptionSub换购事件
。关键是在AbstractBrokerMessageHandler处理消息后发布事件,这意味着订阅已在代理处注册。
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ExecutorChannelInterceptorAdapter() {
@Override
public void afterMessageHandled(Message<?> message, MessageChannel channel, MessageHandler handler, Exception ex) {
SimpMessageHeaderAccessor accessor = SimpMessageHeaderAccessor.wrap(message);
if (accessor.getMessageType() == SimpMessageType.SUBSCRIBE && handler instanceof AbstractBrokerMessageHandler) {
/*
* Publish a new session subscribed event AFTER the client
* has been subscribed to the broker. Before spring was
* publishing the event after receiving the message but not
* necessarily after the subscription occurred. There was a
* race condition because the subscription was being done on
* a separate thread.
*/
applicationEventPublisher.publishEvent(new SessionSubscribedEvent(this, message));
}
}
});
}
您面临的问题在于clientInboundChannel
的性质,默认情况下,它是executorSubscribebalChannel
。
它有3个订户:
0 = {SimpleBrokerMessageHandler@5276} "SimpleBroker[DefaultSubscriptionRegistry[cache[0 destination(s)], registry[0 sessions]]]"
1 = {UserDestinationMessageHandler@5277} "UserDestinationMessageHandler[DefaultUserDestinationResolver[prefix=/user/]]"
2 = {SimpAnnotationMethodMessageHandler@5278} "SimpAnnotationMethodMessageHandler[prefixes=[/app/]]"
在taskExec导师
中调用,因此是异步的。
这里的第一个(SimpleBrokerMessageHandler
(或StompBrokerRelayMessageHandler
)如果您使用代理中继
),负责注册主题
的订阅
。
在WebSocket会话的订阅注册之前,可以执行您的MessagingTemplate.convertAnd发送(/title/path,"msg")
操作,因为它们是在单独的线程中执行的。因此,Broker处理程序不知道您要向会话发送消息。
可以在方法上配置返回
,其中此方法的结果将作为对客户端上的订阅
函数的回复发送。
嗯
我正在构建一个无状态Spring(4.2.4.RELEASE)解决方案,使用STOMP over Websockets和SockJS,以及使用JWT连接移动设备和全双工通信的Restendpoint。我使用Tomcat 8.0.33作为Web服务器,并使用html和sockjs javascript客户端进行测试。stomp协议使用http回退可以很好地工作,但我不能仅使用websocket协议。
我使用的是Spring版本4.3.6。在服务器端和bowers客户端上发布"Stamp-webSocket":"2.0"和"Sockjs-Client":"1.1.4" 以下是服务器端的所有相关代码- 在客户机上,这是代码- Websocket connect建立后,我收到心跳消息,但没有收到我正在发送的通知。我甚至尝试过使用@SendTo注释,但它不起作用。 当我使用webjarstomp和so
尝试使用Spring 4 WebSocket与STOMP通过使用Sockjs套接字。我面临一个问题。 我的配置: websocket.xml-Spring上下文的一部分 控制器代码: 客户端: 输出: 我做错了什么? 我在谷歌(TickerStocks或类似的东西,问候应用程序(Spring的例子))中找到了一些例子,所有这些都给了我同样的错误。我尝试使用WebSocket进行握手(不使用sock
使用SockJS java客户机,我试图连接到Spring SockJS服务器,但对于大约20KB的消息(没有标头),错误为1009。Javascript库工作正常。 还必须将Java SockJS客户端配置为接收更大的消息。 或者,服务器上的配置仍然错误。 如何在Java SockJS Spring客户机上增加缓冲区大小?
我们正在将SpringWebSockets集成到我们的应用程序中,我运行了HelloWorld示例,令人惊讶的是,spring为我们连接了一切,以便将服务器端通知推送到客户端。 不过,我有一些简单的问题 1) 队列是如何创建的?我使用的是ActiveMQ,队列名称与我在目的地中指定的不同(例如,像greetings-user3n9\u jn3i)。 2)目标名称是否不同于队列? 3) 我正在使用A
问题内容: 如何仅从服务器向特定用户发送websocket消息? 我的webapp具有spring安全设置,并使用websocket。我在尝试仅从服务器向特定用户发送消息时遇到棘手的问题。 通过阅读手册,我的理解是来自我们可以做的服务器 在客户端: 但是我永远无法调用订阅回调。我尝试了许多不同的方法,但是没有运气。 如果我将其发送到/ topic / reply,它可以工作,但所有其他已连接用户也