2014-08-29 21 views
5

Tôi đang sử dụng khuôn khổ mùa xuân và tôi có một bộ điều khiển WebSocket làm việc đó trông như thế này:Gửi tin nhắn cho tất cả các khách hàng thông qua SimpMessagingTemplate trong ServletContextListener

@Controller 
public class GreetingController { 

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

Tôi cũng có cấu hình này:

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

Phần đó hoạt động rất tốt! Tôi có thể gửi và nhận thành công tin nhắn giữa hai hoặc nhiều trình duyệt bằng cách sử dụng Stomp.js. Đây là phần không hoạt động. Tôi đã thực hiện một ServletContextListener có chứa một đối tượng tùy chỉnh mà, vì lợi ích đơn giản, tôi đã gọi là 'notifier'. Trình thông báo sẽ lắng nghe các sự kiện nhất định xảy ra ở phía máy chủ. Sau đó nó gọi phương thức 'thông báo', được cho là gửi chi tiết về sự kiện cho tất cả khách hàng. Nó không hoạt động, mặc dù.

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

Tôi không nhận được một ngoại lệ. Các SimpMessagingTemplate đã được tiêm thành công bởi mùa xuân, do đó, nó không phải là null. Tôi đã có thể bước vào mã Spring và đã tìm ra rằngcủa SimpleBrokerMessageHandler bị trống khi sử dụng SimpMessagingTemplate. Vì vậy, nó phải là một trường hợp riêng biệt từ một trong đó các bộ điều khiển đang sử dụng. Làm thế nào tôi có thể nhận được cùng một subscriptionRegistry được sử dụng bởi các bộ điều khiển?

+0

Tò mò nếu bạn tìm thấy một câu trả lời. Hành vi tương tự xảy ra khi gọi từ lớp Spring ApplicationEvent. –

+0

Xin lỗi vì đã quay lại điều này sau rất nhiều thời gian. Tôi đã đăng giải pháp của tôi dưới đây. – battmanz

Trả lời

1

Giải pháp là sử dụng lớp học ApplicationListener của Spring thay vì ServletContextListener và để nghe cụ thể cho ContextRefreshedEvent.

Đây là ví dụ làm việc của tôi:

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

Thông báo, NotifierFactor và Notifier là gì? xin vui lòng giúp đỡ, tôi chỉ muốn gọi websocket của tôi. –

+0

Đó là những trừu tượng mà tôi đã phát minh ra tại chỗ để minh họa cho quan điểm của tôi. Tuy nhiên, chúng đại diện cho các dịch vụ trong thế giới thực mà bạn có thể có trong ứng dụng của mình. Nếu bạn đang sử dụng một WebSocket, sau đó tôi giả sử bạn có một số sự kiện phía máy chủ xảy ra mà bạn muốn đẩy một tin nhắn cho khách hàng. Những trừu tượng đó đại diện cho sự kiện phía máy chủ đó. – battmanz

+0

Tôi có SimpMessagingTemplate trong cùng một lớp như bộ điều khiển, và tôi đang gọi webserice để gọi websocket bằng cách sử dụng templet, không có lỗi nhưng websocket của tôi không được gọi. –

Các vấn đề liên quan