Spring Websocket ChannelInterceptor 未触发 CONNECT 事件
Spring Websocket ChannelInterceptor not firing CONNECT event
我正在使用 Spring 编写简单的 Stomp Websocket 应用程序,客户端都是 Web (JS) 和移动端(ios、android)。从通过 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
方法中 - OK
- 当我关闭连接时,在同一个地方
DISCONNECT
命令会触发两次。 - 不行
当我通过 SockJS 后面的 Websocket 连接时 (ws://localhost:8080/gs-guide-websocket/websocket):
- 我无法在
MyChannelInterceptor
中捕获 CONNECT
命令,在 postSend
方法中 - CRITICAL
- 当我关闭连接时,
DISCONNECT
命令正确触发一次。 - 好的
基本上,虽然我不明白为什么 sockjs 会尝试断开连接两次,但我可以接受。
但是拦截器没有捕获每个连接事件——我活不下去了,因为我要跟踪用户会话,并从那个拦截器中存储它们。
- 我已经尝试在配置中删除
.withSockJs()
- 并且只连接到套接字 - 同样的问题
- 我还尝试在
SessionConnectEvent
和 SessionConnectedEvent
上实现应用程序事件侦听器 - 同样的问题
现在我完全被困住了,不知道从这里还能去哪里......
感谢任何帮助或起点。
非常感谢您对我的痛苦的关注 =(
在 Spring Github 发布问题并在那里交谈后,我发现这不是错误,基本上不是问题,只是我的错:
- DISCONNECT 的行为是预期的。 Spring WebSocket 文档中的拦截、事件和监控章节下的多个位置都提到了它。
- CONNECT 事件预计不会在通过普通 Websockets 连接时触发,因为它只是通过普通 WebSocket 协议建立连接,对于 STOMP 事件,您需要使用 STOMP 客户端。
有兴趣的朋友可以参考相应的讨论帖:
https://github.com/spring-projects/spring-framework/issues/24269
我正在使用 Spring 编写简单的 Stomp Websocket 应用程序,客户端都是 Web (JS) 和移动端(ios、android)。从通过 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
方法中 - OK - 当我关闭连接时,在同一个地方
DISCONNECT
命令会触发两次。 - 不行
当我通过 SockJS 后面的 Websocket 连接时 (ws://localhost:8080/gs-guide-websocket/websocket):
- 我无法在
MyChannelInterceptor
中捕获CONNECT
命令,在postSend
方法中 - CRITICAL - 当我关闭连接时,
DISCONNECT
命令正确触发一次。 - 好的
基本上,虽然我不明白为什么 sockjs 会尝试断开连接两次,但我可以接受。 但是拦截器没有捕获每个连接事件——我活不下去了,因为我要跟踪用户会话,并从那个拦截器中存储它们。
- 我已经尝试在配置中删除
.withSockJs()
- 并且只连接到套接字 - 同样的问题 - 我还尝试在
SessionConnectEvent
和SessionConnectedEvent
上实现应用程序事件侦听器 - 同样的问题
现在我完全被困住了,不知道从这里还能去哪里...... 感谢任何帮助或起点。
非常感谢您对我的痛苦的关注 =(
在 Spring Github 发布问题并在那里交谈后,我发现这不是错误,基本上不是问题,只是我的错:
- DISCONNECT 的行为是预期的。 Spring WebSocket 文档中的拦截、事件和监控章节下的多个位置都提到了它。
- CONNECT 事件预计不会在通过普通 Websockets 连接时触发,因为它只是通过普通 WebSocket 协议建立连接,对于 STOMP 事件,您需要使用 STOMP 客户端。
有兴趣的朋友可以参考相应的讨论帖: https://github.com/spring-projects/spring-framework/issues/24269