如何在连接事件(SockJS,STOMP,Spring)上发送消息?

时间:2014-07-15 10:52:49

标签: spring spring-websocket sockjs

我通过SOMJS通过STOMP连接到我的Spring后端。一切正常,配置适用于所有浏览器等。但是,我找不到发送初始消息的方法。方案如下:

  1. 客户端连接到主题
  2. 
        function connect() {
            var socket = new SockJS('http://localhost:8080/myEndpoint');
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/notify', function(message){
                    showMessage(JSON.parse(message.body).content);
                });
            });
        }
    
    

    并且后端配置看起来或多或少像这样:

    
        @Configuration
        @EnableWebSocketMessageBroker
        public class WebSocketAppConfig extends AbstractWebSocketMessageBrokerConfigurer {   
        ...
        @Override
        public void registerStompEndpoints(final StompEndpointRegistry registry) {
            registry.addEndpoint("/myEndpoint").withSockJS();
        }
    
    
    1. 我想从后端(在连接事件上)向客户端发送一个自动回复,这样我就可以为他提供一些数据集(例如从数据库中读取数据集)而无需他(客户端)发送GET请求(或任何其他)。总而言之,我只是想在他连接之后用SimMessagingTemplate对象向他发送关于该主题的消息。
    2. 通常我会按照以下方式进行,例如:在REST控制器中,当模板已经自动装配时:

      
          @Autowired
          private SimpMessagingTemplate template;
          ...
          template.convertAndSend(TOPIC, new Message("it works!"));
      
      

      如何在连接事件中实现此目的?

      更新

      我设法让它发挥作用。但是,我仍然对配置有点困惑。我将在这里显示2个配置如何发送初始消息:

      1)第一个解决方案

      JS部分

      stompClient.subscribe('/app/pending', function(message){
          showMessage(JSON.parse(message.body).content);
      });
      stompClient.subscribe('/topic/incoming', function(message){
          showMessage(JSON.parse(message.body).content);
      });
      

      Java部分

      @Controller
      public class WebSocketBusController {
          @SubscribeMapping("/pending")
      

      配置

      @Override
      public void configureMessageBroker(final MessageBrokerRegistry config) {
          config.enableSimpleBroker("/topic");
          config.setApplicationDestinationPrefixes("/app");
      }
      

      ......和其他电话

      template.convertAndSend("/topic/incoming", outgoingMessage);
      

      2)第二个解决方案

      JS部分

      stompClient.subscribe('/topic/incoming', function(message){
          showMessage(JSON.parse(message.body).content);
      })
      

      Java部分

      @Controller
      public class WebSocketBusController {
          @SubscribeMapping("/topic/incoming")
      

      配置

      @Override
      public void configureMessageBroker(final MessageBrokerRegistry config) {
          config.enableSimpleBroker("/topic");
          // NO APPLICATION PREFIX HERE
      }
      

      ......和其他电话

      template.convertAndSend("/topic/incoming", outgoingMessage);
      

      内容:

      第一种情况使用了两个订阅 - 这是我想要避免的,并认为只能用一个订阅。

      然而,第二个没有申请前缀。但至少我可以有一个订阅来听取提供的主题以及发送初始消息。

2 个答案:

答案 0 :(得分:3)

如果您只想在连接时向客户端发送消息,请使用适当的ApplicationListener:

@Component
public class StompConnectedEvent implements ApplicationListener<SessionConnectedEvent> {

    private static final Logger log = Logger.getLogger(StompConnectedEvent.class);

    @Autowired
    private Controller controller;

    @Override
    public void onApplicationEvent(SessionConnectedEvent event) {
        log.debug("Client connected.");
        // you can use a controller to send your msg here
    }
}

答案 1 :(得分:0)

您无法在connect上执行该操作,但@SubscribeMapping会执行此类操作。

您只需要使用该注释标记服务方法,并将结果返回给subscribe函数。

从Spring参考手册:

  

@SubscribeMapping注释也可用于将订阅请求映射到@Controller方法。它在方法级别上受支持,但也可以与类型级别@MessageMapping注释结合使用,该注释表示同一控制器中所有消息处理方法的共享映射。

     

默认情况下,@ SubsscribeMapping方法的返回值作为消息直接发送回连接的客户端,并且不通过代理。这对于实现请求 - 回复消息交互很有用;例如,在初始化应用程序UI时获取应用程序数据。或者可以使用@SendTo注释@SubscribeMapping方法,在这种情况下,生成的消息将被发送到&#34; brokerChannel&#34;使用指定的目标目的地。

<强>更新

  

参考这个例子:https://github.com/revelfire/spring4Test当调用index.html的第24行时,如何发送任何内容:stompClient.subscribe(&#39; / user / queue / socket / responses&# 39; ......来自弹簧控制器?

好吧,看起来像这样:

@SubscribeMapping("/queue/socket/responses")
public List<Employee> list() {
     return getEmployees();
}

Stomp客户端部分保持不变。