我在Spring组件中有方法,它从Spring Integration通道接收消息。收到消息后,会将其发送到WebSocket端点。这不起作用。该消息未被广播。
this.messagingTemplate.convertAndSend("/topic/update", dto);
然而,当我在Web控制器中放入相同的代码并在其上放置RequestMapping并调用该端点时,它可以工作。消息是广播的。
当Spring集成执行程序调用它时,它可能导致它不起作用吗?
工作时:.14:01:19.939 [http-nio-8080-exec-4] DEBUG o.s.m.s.b.SimpleBrokerMessageHandler - 处理MESSAGE目的地= / topic / update session = null payload = {XXX} .14:01:19.939 [http-nio-8080-exec-4] DEBUG o.s.m.s.b.SimpleBrokerMessageHandler - 广播到1个会话。
当它不起作用时,第二条消息不存在。 (thread是taskExecutor-1而不是http-nio ..)
控制器代码:
@RequestMapping("/testreq")
public void updateDelta() {
SummaryDTO dto = new SummaryDTO();
dto.setValue(-5000.0);
dto.setName("G");
this.messagingTemplate.convertAndSend("/topic/update", dto);
}
//this method is called by Spring Integration
//created by serviceActivator = new
//ServiceActivatingHandler(webcontroller,"update");
public void updateDelta(SummaryDTO dto) {
this.messagingTemplate.convertAndSend("/topic/update", dto);
}
消息发送:
synchronized(this){
...
this.updatedcontrollerchannel.send(MessageBuilder.withPayload(summarydto).build( )); }
频道制作:
updatedchannel = new DirectChannel();
updatedchannel.setBeanName("updatedcontroller");
serviceActivator = new ServiceActivatingHandler(detailService,"update");
handlerlist.add(serviceActivator);
updatedchannel.subscribe(serviceActivator);
beanFactory.registerSingleton("updatedcontroller", channel);
UPDATE 我在我的环境中添加了Spring消息源代码并实现了以下内容:运行时中有两个SimpleBrokerMessageHandler类实例。对于工作副本,subscriptionregistry有一个条目,对于非工作条目,它有0个订阅。这是否为问题的根本原因提供了线索?只定义了一个MessageSendingOperations变量,它位于控制器上。
答案 0 :(得分:2)
我找到了问题的原因。具有@EnableWebSocketMessageBroker注释的类被加载两次,导致创建了两个SimpleBrokerMessageHandler实例。 @Artem Bilan:谢谢你的时间。
答案 1 :(得分:1)
非正确注入的SimpMessageSendingOperations
。
此内容由AbstractMessageBrokerConfiguration.brokerMessagingTemplate()
@Bean
填充。
但是,我建议您查看Spring Integration中的WebSocketOutboundMessageHandler
:https://docs.spring.io/spring-integration/docs/4.3.12.RELEASE/reference/html/web-sockets.html
<强>更新强>
这在测试用例中对我有用:
@Bean
@InboundChannelAdapter(channel = "nullChannel", poller = @Poller(fixedDelay = "1000"))
public Supplier<?> webSocketPublisher(SimpMessagingTemplate brokerMessagingTemplate) {
return () -> {
brokerMessagingTemplate.convertAndSend("/topic/foo", "foo");
return "foo";
};
}
我有这个DEBUG日志:
12:57:27.606 DEBUG [task-scheduler-1][org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler] Processing MESSAGE destination=/topic/foo session=null payload=foo
12:57:27.897 DEBUG [clientInboundChannel-2][org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler] Processing SUBSCRIBE /topic/foo id=subs1 session=941a940bf07c47a1ac786c1adfdb6299
12:57:40.797 DEBUG [task-scheduler-1][org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler] Processing MESSAGE destination=/topic/foo session=null payload=foo
12:57:40.798 DEBUG [task-scheduler-1][org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler] Broadcasting to 1 sessions.
一切都适用于Spring Integration。
这就是为什么我要求你的整个Spring Boot应用程序在我们这边玩。
更新2
开发Web应用程序时,请务必将所有配置上下文合并到一个应用程序上下文中 - WebApplicationContext
:
如果不需要应用程序上下文层次结构,则应用程序可以通过
getRootConfigClasses()
返回所有配置,并从getServletConfigClasses()
返回null。
在Spring Framework Reference Manual中查看更多信息。