通过ServletContextListener中的SimpMessagingTemplate向所有客户端发送消息

我正在使用Spring框架,我有一个工作的websocket控制器,如下所示:

@Controller public class GreetingController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws InterruptedException { return new Greeting("Hello, " + message.getName() + "!"); } } 

我也有这个配置:

 @Configuration @EnableWebSocketMessageBroker public class HelloWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/hello").withSockJS(); } } 

那部分效果很好! 我可以使用Stomp.js在两个或多个浏览器之间成功发送和接收消息。 这是不起作用的部分。 我已经实现了一个ServletContextListener ,它包含一个自定义对象,为简单起见,我称之为“通知器”。 通知程序侦听在服务器端发生的某些事件。 然后它调用’notify’方法,该方法应该将有关事件的详细信息发送给所有客户端。 但它不起作用。

 @WebListener public class MessageListener implements ServletContextListener, Notifiable { private Notifier notifier; @Autowired private SimpMessagingTemplate messageSender; public MessageListener() { notifier = new Notifier(this); } public void contextInitialized(ServletContextEvent contextEvent) { WebApplicationContextUtils .getRequiredWebApplicationContext(contextEvent.getServletContext()) .getAutowireCapableBeanFactory() .autowireBean(this); notifier.start(); } public void contextDestroyed(ServletContextEvent contextEvent) { notifier.stop(); } public void notify(NotifyEvent event) { messageSender.convertAndSend("/topic/greetings", new Greeting("Hello, " + event.subject + "!")); } } 

我没有例外。 Spring已经成功注入了SimpMessagingTemplate ,因此它不是null。 我已经能够进入Spring代码,并且在使用SimpMessagingTemplate时已经发现SimpMessagingTemplatesubscriptionRegistry是空的。 因此它必须是与控制器正在使用的实例不同的实例。 如何获得控制器使用的相同subscriptionRegistry

解决方案是使用Spring的ApplicationListener类而不是ServletContextListener ,并专门监听ContextRefreshedEvent

这是我的工作示例:

 @Component public class MessagingApplicationListener implements ApplicationListener, Notifiable { private final NotifierFactor notifierFactory; private final MessageSendingOperations messagingTemplate; private Notifier notifier; @Autowired public MessagingApplicationListener(NotifierFactor notifierFactory, MessageSendingOperations messagingTemplate) { this.notifierFactory = notifierFactory; this.messagingTemplate = messagingTemplate; } @Override public void onApplicationEvent(ContextRefreshedEvent event) { if (notifier == null) { notifier = notifierFactory.create(this); notifier.start(); } } public void notify(NotifyEvent event) { messagingTemplate.convertAndSend("/topic/greetings", new Greeting("Hello, " + event.subject + "!")); } @PreDestroy private void stopNotifier() { if (notifier != null) { notifier.stop(); } } }