Отправить сообщение всем клиентам через SimpMessagingTemplate в ServletContextListener
Я использую Spring framework, и у меня есть рабочий контроллер 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 + "!"));
}
}
Я не получаю исключение. The SimpMessagingTemplate
был успешно введен весной, поэтому он не является нулевым. Я смог войти в весенний код и понял, что SimpleBrokerMessageHandler
' s subscriptionRegistry
пуст при использовании SimpMessagingTemplate
. Таким образом, это должен быть отдельный экземпляр от того, который используют контроллеры. Как может Я получаю то же самое subscriptionRegistry
что используется контроллерами?
1 ответов
решение было использовать весной ApplicationListener
класса вместо ServletContextListener
, и специально слушать для ContextRefreshedEvent
.
вот мой рабочий пример:
@Component
public class MessagingApplicationListener implements ApplicationListener<ContextRefreshedEvent>, Notifiable {
private final NotifierFactor notifierFactory;
private final MessageSendingOperations<String> messagingTemplate;
private Notifier notifier;
@Autowired
public MessagingApplicationListener(NotifierFactor notifierFactory, MessageSendingOperations<String> 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();
}
}
}