socket servidor ejemplo cliente java spring spring-mvc websocket spring-websocket

java - servidor - Enviar mensaje a todos los clientes a través de SimpMessagingTemplate en ServletContextListener



socket java ejemplo (1)

La solución fue utilizar la clase ApplicationListener de Spring en lugar de ServletContextListener , y escuchar específicamente ContextRefreshedEvent .

Este es mi ejemplo de trabajo:

@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(); } } }

Estoy usando el framework Spring y tengo un controlador websocket que funciona así:

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

También tengo esta configuración:

@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(); } }

Esa parte funciona muy bien! Puedo enviar y recibir mensajes con éxito entre dos o más navegadores usando Stomp.js. Aquí está la parte que no funciona. He implementado un ServletContextListener que contiene un objeto personalizado que, por simplicidad, he llamado ''notificador''. El notificador escucha que ocurran ciertos eventos en el lado del servidor. Luego llama al método ''notify'', que se supone que envía detalles sobre el evento a todos los clientes. Sin embargo, no funciona.

@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 + "!")); } }

No tengo una excepción SimpMessagingTemplate ha sido inyectado con éxito por Spring, por lo que no es nulo. He podido entrar en el código de Spring y he descubierto que el SimpleBrokerMessageHandler de SimpleBrokerMessageHandler está vacío cuando se utiliza SimpMessagingTemplate . Por lo tanto, debe ser una instancia diferente de la que usan los controladores. ¿Cómo puedo obtener el mismo subscriptionRegistry que utilizan los controladores?