Spring STOMP WebSocket会话断开事件未触发,如何正确监听实现重连?
我来帮你排查这个问题,你遇到的SessionDisconnectEvent没触发的情况,通常有几个常见原因,咱们一步步来解决:
1. 移除冗余的事件监听配置
你当前的代码同时实现了ApplicationListener<SessionDisconnectEvent>接口,又添加了@EventListener注解——这两种监听方式选一种就好,冗余配置可能导致Spring无法正确识别监听逻辑。推荐简化代码,二选一:
方式A:仅实现ApplicationListener接口
@Component public class SessionDisconnectListener implements ApplicationListener<SessionDisconnectEvent> { @Override public void onApplicationEvent(SessionDisconnectEvent applicationEvent) { System.out.println("SESSION " + applicationEvent.getSessionId() + " DISCONNECTED"); } }
方式B:仅使用@EventListener注解(更简洁)
@Component public class SessionDisconnectListener { @EventListener public void handleSessionDisconnect(SessionDisconnectEvent event) { System.out.println("SESSION " + event.getSessionId() + " DISCONNECTED"); } }
2. 检查WebSocket消息代理配置是否正确
如果你的应用是STOMP服务器(接收其他微服务连接),要确保WebSocketMessageBrokerConfigurer配置没有禁用事件发布逻辑。默认情况下Spring会自动发布SessionDisconnectEvent,但如果你的配置类有自定义逻辑,需确认没有覆盖相关行为:
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); // 若需心跳检测(及时感知异常断开),可添加如下配置 config.enableSimpleBroker("/topic") .setHeartbeatValue(new long[]{10000, 10000}); // 客户端/服务器每10秒互发心跳 } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); } }
3. 区分你的应用是STOMP服务器还是客户端
如果你的应用是STOMP客户端(主动连接其他微服务的STOMP服务器),默认Spring不会自动发布SessionDisconnectEvent。这时候需要通过自定义StompSessionHandler来监听断开事件:
@Component public class CustomStompSessionHandler extends StompSessionHandlerAdapter { @Override public void afterConnected(StompSession session, StompHeaders connectedHeaders) { System.out.println("Connected to STOMP server, session id: " + session.getSessionId()); } @Override public void afterDisconnected(StompSession session, StompHeaders headers, StompFrameHandler handler) { // 会话断开后触发,在这里处理重连逻辑 System.out.println("SESSION " + session.getSessionId() + " DISCONNECTED"); reconnect(); } @Override public void handleTransportError(StompSession session, Throwable exception) { // 连接出错时触发(比如网络中断),可提前做异常处理 System.err.println("Transport error for session: " + session.getSessionId()); } private void reconnect() { // 实现你的重连逻辑,比如用定时任务重试连接 // 示例:使用ScheduledExecutorService延迟3秒重试 new ScheduledThreadPoolExecutor(1).schedule(() -> { // 调用你的连接方法 connectToServer(); }, 3, TimeUnit.SECONDS); } private void connectToServer() { WebSocketClient webSocketClient = new StandardWebSocketClient(); StompClient stompClient = new StompClient(webSocketClient); stompClient.connect("ws://target-microservice/ws", this); } }
4. 确认触发事件的场景
注意SessionDisconnectEvent(服务器端)只会在以下场景被发布:
- 客户端主动发送
DISCONNECT帧 - 客户端心跳超时(需配置心跳检测)
- 服务器主动断开连接
如果是客户端异常断开(比如突然断电、网络中断),必须配置心跳检测才能让服务器及时感知并发布事件。
内容的提问来源于stack exchange,提问作者Michael Dz
相关产品推荐
相关产品推荐

