WebSocket消息不会一直传递

时间:2019-08-23 10:28:19

标签: spring spring-boot websocket stomp sockjs

我有一个带有WebSockets的应用程序,该应用程序使用spring-boot应用程序作为后端,并在客户端使用Stomp / SockJS,spring-boot应用程序使用JMS队列消息并将更改通知给正确的用户。问题是什么?有时可行,有时不可行,相同的代码和用户可以正常工作。

在这里,客户端代码很难复制,因为它是通过react / redux应用程序集成的,但是基本上是对两个不同通道的订阅,这两个通道都在Spring的配置中定义。会话是根据调试信息正确创建的,但有时会处理该消息以将其发送到连接的会话。

这是Spring的配置类。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

   @Override
   public void registerStompEndpoints(StompEndpointRegistry registry) {

      registry
         .addEndpoint("/stomp")
         .setAllowedOrigins("*")
         .withSockJS();
   }

   public void configureMessageBroker(MessageBrokerRegistry registry) {

      registry
         .setApplicationDestinationPrefixes("/app")
         .enableSimpleBroker("/xxxx/yyyy", "/ccccc");
   }

   @Override
   public void configureClientInboundChannel(ChannelRegistration registration) {

      registration.interceptors(new ChannelInterceptor() {

         @Override
         public Message<?> preSend(Message<?> message, MessageChannel channel) {

             StompHeaderAccessor accessor =
                     MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

             if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                 Object raw = message
                         .getHeaders()
                         .get(SimpMessageHeaderAccessor.NATIVE_HEADERS);

                 if (raw instanceof Map) {
                     Object name = ((Map<?,?>) raw).get("email");

                     if (name instanceof LinkedList) {
                         String user = ((LinkedList<?>) name).get(0).toString();
                         accessor.setUser(new User(user));
                     }
                 }
             }
             return message;
         }
      });
   }
}

这是JMS侦听器,用于处理队列消息并将其发送给特定用户。

@Component
public class UserEventListener {

   private final Logger logger = LoggerFactory.getLogger(getClass());
   private final SimpMessagingTemplate template;

   @Autowired
   public UserEventListener(SimpMessagingTemplate pTemplate) {
      this.template = pTemplate;
   }

   @JmsListener(destination="user/events")
   public void onStatusChange(Map<String, Object> props) {

      if (props.containsKey("userEmail")) {
         logger.debug("Event for user received: {}", props.get("userEmail"));
         template.convertAndSendToUser((String)props.get("userEmail"), "/ccccc", props);
      }
   }
}

编辑1:

经过更多的调试之后,WebSocket的“会话”似乎因Spring配置而丢失了。我没有看到有关“断开连接”消息或类似内容的任何日志信息,此外,如果在发生这种情况时远程调试服务器,则在调试会话期间不会出现问题。有想法吗来自Spring的会话消失的班级是DefaultSimpUserRegistry

1 个答案:

答案 0 :(得分:0)

经过更多研究,我发现了一个具有相同问题的问题和解决方案here。基本上结论是这样的:

通道拦截器不是验证用户身份的正确位置,我们需要使用自定义的握手处理程序对其进行更改。