Java WebSocket
WebSocket是基于HTTP升级的全双工通信协议,适用于实时推送场景。
WebSocket特点
| 特点 | 说明 |
|---|---|
| 全双工 | 客户端和服务端同时发送 |
| 持久连接 | 一次握手,持续通信 |
| 低开销 | 无HTTP头部开销 |
| 实时性 | 消息即时推送 |
| 二进制支持 | 可传输二进制数据 |
WebSocket vs HTTP
| 特性 | WebSocket | HTTP |
|---|---|---|
| 通信模式 | 双向 | 请求-响应 |
| 连接 | 持久 | 短连接 |
| 头部开销 | 极低 | 较大 |
| 实时性 | 实时推送 | 需轮询 |
| 协议标识 | ws:// / wss:// | http:// / https:// |
协议握手流程
Java
客户端 服务端
| |
|── HTTP请求(Upgrade)──────────→|
| GET /chat HTTP/1.1 |
| Upgrade: websocket |
| Connection: Upgrade |
| Sec-WebSocket-Key: xxx |
| |
|←── HTTP响应(101 Switching)────|
| HTTP/1.1 101 Switching Protocols|
| Upgrade: websocket |
| Sec-WebSocket-Accept: xxx |
| |
========== WebSocket连接建立 ==========
| |
|←────── 数据帧 ───────────────────| 双向通信
|────── 数据帧 ──────────────────→|
Java WebSocket服务端(JSR-356)
注解方式
Java
@ServerEndpoint("/chat")
public class ChatEndpoint {
private Session session;
@OnOpen
public void onOpen(Session session) {
this.session = session;
System.out.println("连接打开: " + session.getId());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("收到消息: " + message);
// 回送消息
session.getAsyncRemote().sendText("Echo: " + message);
}
@OnClose
public void onClose(Session session, CloseReason reason) {
System.out.println("连接关闭: " + reason.getReasonPhrase());
}
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误: " + error.getMessage());
}
// 发送消息到所有客户端
public static void broadcast(String message) {
for (Session session : sessionSet) {
session.getAsyncRemote().sendText(message);
}
}
}
配置发布
Java
public class WebSocketServer {
public static void main(String[] args) throws Exception {
Server server = new Server("localhost", 8080, "/ws", ChatEndpoint.class);
server.start();
System.out.println("WebSocket服务端启动: ws://localhost:8080/ws/chat");
}
}
Java WebSocket客户端
注解方式
Java
@ClientEndpoint
public class ChatClient {
private Session session;
@OnOpen
public void onOpen(Session session) {
this.session = session;
System.out.println("已连接服务端");
}
@OnMessage
public void onMessage(String message) {
System.out.println("收到: " + message);
}
@OnClose
public void onClose(Session session, CloseReason reason) {
System.out.println("连接关闭");
}
public void send(String message) {
session.getAsyncRemote().sendText(message);
}
public static void main(String[] args) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
ChatClient client = new ChatClient();
Session session = container.connectToServer(client,
URI.create("ws://localhost:8080/ws/chat"));
// 发送消息
client.send("Hello WebSocket");
Thread.sleep(5000);
session.close();
}
}
Session常用方法
Java
Session session = ...;
// 基本信息
String id = session.getId();
URI uri = session.getRequestURI();
boolean open = session.isOpen();
// 发送消息
session.getBasicRemote().sendText("文本消息"); // 同步发送
session.getAsyncRemote().sendText("文本消息"); // 异步发送
session.getBasicRemote().sendBinary(ByteBuffer.wrap(bytes)); // 二进制
// 发送对象(需配置编码器)
session.getBasicRemote().sendObject(userObject);
// 关闭连接
session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "正常关闭"));
// 用户属性
session.getUserProperties().put("username", "张三");
String username = (String) session.getUserProperties().get("username");
// 最大空闲超时
session.setMaxIdleTimeout(30000); // 30秒无活动则关闭
// 最大消息大小
session.setMaxBinaryMessageBufferSize(64 * 1024);
session.setMaxTextMessageBufferSize(64 * 1024);
Spring Boot WebSocket
配置
Java
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new ChatHandler(), "/chat")
.setAllowedOrigins("*");
}
}
Handler实现
text
public class ChatHandler extends TextWebSocketHandler {
private final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.add(session);
System.out.println("新连接: " + session.getId());
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
String payload = message.getPayload();
System.out.println("收到: " + payload);
// 广播给所有客户端
for (WebSocketSession s : sessions) {
if (s.isOpen()) {
s.sendMessage(new TextMessage(payload));
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
sessions.remove(session);
System.out.println("连接关闭: " + session.getId());
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
System.out.println("传输错误: " + exception.getMessage());
}
}
适用场景
| 场景 | 说明 |
|---|---|
| 即时聊天 | 实时消息推送 |
| 协作编辑 | 多人实时编辑 |
| 实时监控 | 服务器状态推送 |
| 股票行情 | 实时价格更新 |
| 游戏对战 | 实时状态同步 |
注意事项
WebSocket基于HTTP升级,握手阶段使用HTTP
wss:// 是安全WebSocket,类似HTTPS
连断后需实现重连机制
大量连接时注意资源管理
心跳机制检测连接状态
要点总结
- WebSocket全双工通信,一次握手持久连接
- 通过HTTP Upgrade升级建立连接
- Java使用 @ServerEndpoint/@ClientEndpoint 注解开发
- Session 提供发送消息和管理连接的方法
- 适用于聊天、监控、游戏等实时场景
📝 发现内容有误?点击此处直接编辑