【问题标题】:Websocket Push Notifications not working AFTER spring boot upgrade from 1.2.0 to 2.1.3春季启动从 1.2.0 升级到 2.1.3 后,Websocket 推送通知不起作用
【发布时间】:2019-07-29 17:02:35
【问题描述】:

这是关于使用 websocket + stompjs 发送推送通知的 spring boot + angularjs web 应用程序。

我最近从 Spring boot 1.2.0 升级到 2.1.3之前,此升级 websocket(推送通知)工作了好几年

我刚刚升级了 spring boot 和 websocket 相关的代码完全相同,但它现在工作了。

不工作意味着:

  1. 在服务器端执行以下行没有任何错误/异常。

simpMessagingTemplate.convertAndSend("/topic/notify", payload);

  1. Chrome 调试器只接收“h”(心跳)而不是实际消息。

不知道因为,

  • 服务器端代码成功执行直到最后一行
  • websocket 会话建立,我可以收到心跳消息,但客户端也没有错误。

代码(但同样的代码适用于 Spring boot 1.2.0:

1.配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Value("${server.sessionTimeout}")
    long sessionTimeoutInSecs;

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

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/notify").withSockJS();
    }

    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        // in milliseconds
        container.setMaxSessionIdleTimeout(sessionTimeoutInSecs * 1000);
        return container;
    }
}

2。消息发送代码:

simpMessagingTemplate.convertAndSend("/topic/notify", payload);

3.客户端代码:

(function() {
  myApp.factory('autoUpdateTasksService', function($resource, $q, $log) {
    var initSockets, notify, reconnect, socket, _callback;
    _callback = null;
    socket = {
      client: null,
      stomp: null
    };
    initSockets = function() {
      socket.client = new SockJS('/notify');
      socket.stomp = Stomp.over(socket.client);
      socket.stomp.connect({}, function() {});
      socket.client.onopen = function() {
        var subscription1;
        subscription1 = socket.stomp.subscribe("/topic/notify", notify);
        //$log.log('socket connected');
      };
    };
    reconnect = function() {
      setTimeout(initSockets, 1000);
    };
    notify = function(message) {
         try{
              var taskNotifyObject;
                  if (message.body) {
                    taskNotifyObject = angular.fromJson(message.body);
                    //$log.log(taskNotifyObject);
                    var notificationArray=[];
                    notificationArray.push(taskNotifyObject);
                    _callback(notificationArray);
                  } else {
                    //$log.log("empty message");
                  }
             } catch(e){
                // alert(e.message); 
                 }
                };
            return {
              init: function(callback) {
                _callback = callback;
                initSockets();
              }
            };
  });

}).call(this);

版本之间的spring框架有什么变化吗?

如何调试/查找消息丢失的位置?

【问题讨论】:

    标签: spring spring-boot websocket spring-websocket stomp


    【解决方案1】:

    根本原因:升级后,我的问题中的代码无法在服务器和客户端之间创建连接(未能创建websocketSession) .

    更改代码如下解决问题,但我确定为什么这个解决方案有效,

    如果有人解释为什么这个解决方案是有效的,那将是一个很大的帮助。

    1.配置:

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    
        @Value("${server.servlet.session.timeout}")
        long sessionTimeoutInSecs;
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry config) {
            config.enableSimpleBroker("/queue");
            config.setApplicationDestinationPrefixes("/app");
        }
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/notify").addInterceptors(new HttpSessionHandshakeInterceptor());
        }
    
        @Bean
        public ServletServerContainerFactoryBean createWebSocketContainer() {
            ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
            // in milliseconds
            container.setMaxSessionIdleTimeout(sessionTimeoutInSecs * 1000);
            return container;
        }
    
        /**
         * DefaultSimpUserRegistry is the replacement of MySessionRegistry ( Custom UserSessionRegistry ) after upgrade to Spring 5.
         * Below required with Spring 4.
         * import org.springframework.messaging.simp.user.UserSessionRegistry;
            @Repository
            public class MySessionRegistry implements UserSessionRegistry, ApplicationListener<AbstractSubProtocolEvent> {
         * 
         */ 
        @Bean
        public DefaultSimpUserRegistry defaultSimpUserRegistry() {
            DefaultSimpUserRegistry userRegistry = new DefaultSimpUserRegistry();
            return userRegistry;
        }
    }
    

    2。消息发送代码:

    import org.springframework.web.socket.messaging.DefaultSimpUserRegistry;
    
    @Autowired
    DefaultSimpUserRegistry defaultSimpUserRegistry;
    
    .....
    
    SimpUser simpUser = defaultSimpUserRegistry.getUser(payload.getUserName());
    
    if(simpUser != null && simpUser.hasSessions()) {
         template.convertAndSendToUser(payload.getUserName(), "/queue/notify", payload);
    }
    

    3.客户端代码:

    (function() {
      myApp.factory('autoUpdateTasksService', function($resource, $q, $log) {
        var initSockets, notify, reconnect, socket, _callback;
        _callback = null;
        socket = {
          client: null,
          stomp: null
        };
        getContextPath = function() {
            return window.location.pathname.substring(0, window.location.pathname.indexOf("/",2));
        };
        initSockets = function() {
            //socket.addr = "wss://" + window.location.host + "/notify";
            socket.addr = ((window.location.protocol && (window.location.protocol.indexOf("https") >= 0)) ? "wss://" : "ws://") + window.location.host + getContextPath() + "/notify";
            socket.client = Stomp.client(socket.addr); //new SockJS('/notify');
            socket.client.connect({}, function () {
              $log.log("Connected to websocket through " + socket.addr);
              socket.client.subscribe("/user/queue/notify", notify);
            }, function (err) {
              $log.log("Error when connection to websocket " + socket.addr + ".\n" + err);
            });
        };
    

    如何调试/查找消息丢失的位置?

    为了验证客户端-服务器连接(或创建 websocketSession),我在 listener 下方添加。

    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
    import org.springframework.web.socket.messaging.SessionConnectedEvent;
    import org.springframework.web.socket.messaging.SessionSubscribeEvent;
    
    @Component
    public class WebSocketListener implements ApplicationListener <ApplicationEvent> {
    
                //WebSocket session created
                if (appEvent instanceof SessionConnectedEvent){
                    StompHeaderAccessor sha = StompHeaderAccessor.wrap(((SessionConnectedEvent) appEvent).getMessage());
                    logger.info("SessionConnectedEvent: STOMP WebSocket session created for the user: {}", sha.getUser().getName());
                }
    
                //subscribed to websocketSession
                if (appEvent instanceof SessionSubscribeEvent){
                    StompHeaderAccessor sha = StompHeaderAccessor.wrap(((SessionSubscribeEvent) appEvent).getMessage());                
                    logger.info("SessionSubscribeEvent: User {} subscribed to WebSocket session, destination: {}", sha.getUser().getName(), sha.getDestination());
                }
    //            
    //            if (appEvent instanceof BrokerAvailabilityEvent){
    //                logger.info("BrokerAvailabilityEvent: {}", appEvent.toString());
    //            }
            }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-04
      相关资源
      最近更新 更多