本文介绍在 Spring Boot 中使用标准 WebSocket(javax.websocket)实现端到端通信,并补齐心跳与超时控制的关键细节。
在 Spring Boot 内嵌容器环境,注册 ServerEndpointExporter 即可扫描 @ServerEndpoint 标注的端点:
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Component
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint("/ws")
public class WsEndpoint {
private static final ConcurrentHashMap SESSIONS = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session) {
SESSIONS.put(session.getId(), session);
send(session, "{\\"type\\":\\"welcome\\"}");
}
@OnMessage
public void onMessage(String msg, Session session) {
// 根据自定义协议处理消息
send(session, "{\\"type\\":\\"echo\\",\\"data\\":" + msg + "}");
}
@OnClose
public void onClose(Session session) {
SESSIONS.remove(session.getId());
}
@OnError
public void onError(Session session, Throwable t) {
t.printStackTrace();
}
private void send(Session s, String text) {
try { s.getBasicRemote().sendText(text); } catch (Exception ignored) {}
}
}
建议采用“应用层心跳”:客户端定期发送 ping,服务端回复 pong,并在服务端维护最近一次心跳时间戳,超时则主动关闭连接。
// 伪代码:处理心跳
if ("ping".equals(type)) {
lastHeartbeat.put(sessionId, System.currentTimeMillis());
send(session, "{\"type\":\"pong\"}");
}
同时在反向代理层(如 Nginx)提升超时阈值:
location /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
以上示例为教学用途,可按需拓展鉴权、路由与广播等能力。