Java WebSocket断线处理需区分异常类型、隔离状态变更、控制重连节奏、避免资源重复初始化:捕获IO/Timeout/EOF/WebsocketNotConnected异常,不捕获NPE/InterruptedException/OutOfMemoryError;onClose/onError/onOpen仅做轻量状态更新;重连交由独立线程池异步执行,配合状态机与指数退避(1s→2s→4s…上限5次);主动关闭优先调用closeBlocking()或close()并确保资源释放。

Java中用try-catch处理WebSocket断线,不能只靠“捕获异常就重连”——它只是起点,真正妥善的关键在于:区分异常类型、隔离状态变更、控制重连节奏、避免资源重复初始化。
精准识别哪些异常值得捕获
不是所有异常都该进catch块,也不是所有异常都适合触发重连:
- 应捕获:IOException(写心跳失败)、TimeoutException(心跳响应超时)、EOFException(对端静默关闭)、WebsocketNotConnectedException(发消息时连接已断)
- 不应捕获:NullPointerException(说明逻辑有空指针风险,需提前校验)、InterruptedException(应响应中断并退出任务,而非重试)、OutOfMemoryError(系统级错误,无法恢复)
- 特别注意:@OnError方法中收到的Throwable必须打印或记录堆栈——java.io.EOFException往往意味着服务端已RST掉连接,而1006类静默断连根本不会触发onError,只能靠onClose + code判断
在回调中做轻量操作,不直接重连
onClose、onError、onOpen等生命周期回调里,只做状态更新和事件通知,不执行耗时或并发敏感动作:
- onClose中清理资源:从ConcurrentHashMap移除session、取消关联的定时心跳任务、关闭数据库连接池引用
- onError中记录真实Throwable,但不要调用sendText()——此时session大概率已失效,会抛IllegalStateException
- onOpen中重置重连计数器、启动心跳检测器、设置readyState = CONNECTED
- 所有重连调度交给独立的ExecutorService异步执行,避免阻塞Netty/JSR-356事件线程
用状态机+退避策略控制重连行为
裸调connectToServer()或reconnect()极易引发雪崩。可靠做法是引入显式状态与退避逻辑:
立即学习“Java免费学习笔记(深入)”;
- 定义状态枚举:NOT_CONNECTED → CONNECTING → CONNECTED → HEARTBEAT_FAILED → DISCONNECTED
- 心跳失败后调用onHeartbeatFailure(),仅更新状态和失败次数,由协调器决定是否重连
- 重连使用指数退避:首次延迟1s,第二次2s,第三次4s……上限建议5次,第5次失败后停连并告警
- 加状态锁:if (currentState == CONNECTING || currentState == CONNECTED) return,防止多线程重复发起连接
关闭前尽量做到优雅,关后确保资源释放
主动关闭比被动断开更可控,也利于服务端及时清理:
- 发送最后一条业务消息后,再调用close(CloseFrame.NORMAL, "user logout")
- 若使用Java-WebSocket库,优先选closeBlocking()保证I/O完成;如用JSR-356,确保close()调用后不再访问session
- finally块中检查线程池、ScheduledFuture、ByteBuffer等是否已shutdown,避免内存泄漏
- 客户端退出时,强制cancel所有未完成的心跳Future,并interrupt对应线程

















