You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:15:47