Spring Websocket ChannelInterceptor 未触发 CONNECT 事件

Posted

技术标签:

【中文标题】Spring Websocket ChannelInterceptor 未触发 CONNECT 事件【英文标题】:Spring Websocket ChannelInterceptor not firing CONNECT event 【发布时间】:2020-04-15 15:56:32 【问题描述】:

我正在用 Spring 编写简单的 Stomp Websocket 应用程序,客户端既是 web (JS),又是移动 (iosandroid)。从通过 SockJS 连接的 JS 代码客户端,而移动客户端在 SockJS 后面使用普通的 websocket 连接。 问题是我正在检查身份验证的ChannelInterceptor 中的行为对于不同类型的连接完全不同。我不能让它对每个客户都一样。 让我简单地给出一些它背后的代码并举例说明: Websocket starter 取自 Spring 示例:https://github.com/spring-guides/gs-messaging-stomp-websocket.git

Websocket 配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer 

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

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) 
        registry.addEndpoint("/gs-guide-websocket")
                .setAllowedOrigins("*")
                .withSockJS();
    

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) 
        registration.interceptors(new MyChannelInterceptor());
    

还有ChannelInterceptor 本身:

public class MyChannelInterceptor implements ChannelInterceptor 
    @Override
    public void postSend(Message<?> message, MessageChannel channel, boolean sent) 
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        StompCommand command = accessor.getCommand();
        ...
    

当我从 JS 应用程序通过 SockJS 连接时(http://localhost:8080/gs-guide-websocket - 让 Spring SockJS 完成剩下的工作):

    我可以在MyChannelInterceptor 中捕获CONNECT 命令,在postSend 方法中 - 好的 当我关闭连接时,在同一个地方DISCONNECT 命令会触发两次。 - 不行

当我通过 SockJS 后面的 Websocket 连接时 (ws://localhost:8080/gs-guide-websocket/websocket):

    我无法在 MyChannelInterceptorpostSend 方法中捕获 CONNECT 命令 - 严重 当我关闭连接时,DISCONNECT 命令会正确触发一次。 - 好的

基本上,虽然我不明白为什么 sockjs 会尝试断开两次连接,但我可以忍受。 但是拦截器无法捕获每个连接事件 - 我无法生存,因为我要跟踪用户会话,并将它们从那个拦截器中存储。

我已经尝试在配置中删除 .withSockJs() - 并且只是连接到套接字 - 同样的问题 我还尝试在 SessionConnectEventSessionConnectedEvent 上实现应用程序事件侦听器 - 同样的问题

现在我完全被困住了,不知道我还能去哪里...... 感谢任何帮助或起点。

非常感谢您对我的痛苦的关注=(

【问题讨论】:

【参考方案1】:

在Spring Github上发布问题并在那里交谈后,我发现这不是错误,基本上不是问题,而是我的错:

DISCONNECT 的行为是预期的。在 Spring WebSocket 文档的 Interception、Events 和 Monitoring 章节中的多个地方都提到了它。 通过普通 Websocket 连接时,预计不会触发 CONNECT 事件,因为它只是通过普通 WebSocket 协议建立连接,对于 STOMP 事件,您需要使用 STOMP 客户端。

有兴趣的可以参考对应的帖子: https://github.com/spring-projects/spring-framework/issues/24269

【讨论】:

以上是关于Spring Websocket ChannelInterceptor 未触发 CONNECT 事件的主要内容,如果未能解决你的问题,请参考以下文章

Spring 4.0 WebSocket 示例应用程序:无法建立 websocket 连接

spring-webSocket

Spring 4 WebSocket 配置端口

Spring和Java中的Websocket

spring-websocket的搭建

spring websocket WebSocketSession 共享方案