【问题标题】:Send Message to all clients via SimpMessagingTemplate in ServletContextListener通过 ServletContextListener 中的 SimpMessagingTemplate 向所有客户端发送消息
【发布时间】:2014-10-23 01:54:47
【问题描述】:

我正在使用 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,其中包含一个自定义对象,为简单起见,我称之为“通知程序”。通知程序侦听服务器端发生的某些事件。然后它调用“通知”方法,该方法应该将有关事件的详细信息发送给所有客户端。但是,它不起作用。

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

我没有遇到异常。 SimpMessagingTemplate 已经被 Spring 成功注入,所以它不为空。我已经能够进入 Spring 代码并发现使用 SimpMessagingTemplateSimpleBrokerMessageHandlersubscriptionRegistry 是空的。因此,它必须是与控制器正在使用的实例不同的实例。如何获得控制器使用的相同subscriptionRegistry

【问题讨论】:

  • 好奇你是否找到了答案。从 Spring ApplicationEvent 类调用时会发生相同的行为。
  • 很抱歉这么久才回到这个问题。我已经在下面发布了我的解决方案。

标签: java spring spring-mvc websocket spring-websocket


【解决方案1】:

解决方案是使用 Spring 的 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();
        }
    }
}

【讨论】:

  • 什么是 Notifiable、NotifierFactor 和 Notifier ?请帮忙,我只想打电话给我的 websocket。
  • 这些是我为了说明我的观点而当场发明的抽象。但是,它们代表您的应用程序中可能拥有的真实服务。如果您使用的是 WebSocket,那么我假设您发生了一些服务器端事件,您希望将消息推送到客户端。这些抽象只是代表那个服务器端事件。
  • 我有 SimpMessagingTemplate 与控制器在同一个类中,我正在调用 webserice 使用模板调用 websocket,没有错误但我的 websocket 没有被调用。
  • 你能检查这个线程并帮助我stackoverflow.com/questions/38919790/…
【解决方案2】:

这个解决方案效果很好。

对于任何想要快速解决方案的人 - 去掉所有“通知程序”的东西,只需将 MessagingApplicationListener 注入您的课程。然后使用字符串调用“通知”以发送消息。显然,正如@battmanz 所说,您需要某种方式将事件推送到侦听器,但是这个类可以满足您的基本需求。

【讨论】:

    猜你喜欢
    • 2019-04-29
    • 2012-01-18
    • 1970-01-01
    • 2023-03-11
    • 2016-05-25
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    相关资源
    最近更新 更多