WebSocket 是一种在单个 TCP 连接上提供全双工通信的协议,允许客户端和服务器之间进行实时、双向的数据交换。在 Java 中,有多种方式可以实现 WebSocket 功能,主要包括标准的 JSR 356 API 和一些第三方框架。
一、Java WebSocket 规范(JSR 356)
Java EE 7 引入了 JSR 356 规范,定义了 Java 平台的 WebSocket API,使开发者能够标准化地实现 WebSocket 通信。
核心组件
-
**Endpoint(端点)**代表 WebSocket 连接的端点,是客户端与服务器交互的核心。有两种创建方式:
- 编程式 :继承
javax.websocket.Endpoint
类,重写生命周期方法。 - 注解式 :使用注解
@ServerEndpoint
标记类(更常用)。
- 编程式 :继承
-
生命周期方法
@OnOpen
:连接建立时触发。@OnMessage
:收到客户端消息时触发。@OnClose
:连接关闭时触发。@OnError
:发生错误时触发。
-
Session代表一个 WebSocket 连接会话,用于发送消息、管理连接状态等。
二、基本实现示例(注解式)
1. 服务器端代码
java
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
// 定义WebSocket端点的URL路径
@ServerEndpoint("/chat")
public class ChatServer {
// 存储所有连接的会话(线程安全)
private static final Set<Session> sessions =
Collections.newSetFromMap(new ConcurrentHashMap<>());
// 连接建立时调用
@OnOpen
public void onOpen(Session session) {
sessions.add(session);
System.out.println("新连接加入,当前连接数:" + sessions.size());
}
// 收到消息时调用
@OnMessage
public void onMessage(String message, Session session) throws IOException {
System.out.println("收到消息:" + message);
// 广播消息给所有连接的客户端
for (Session s : sessions) {
if (s.isOpen()) {
s.getBasicRemote().sendText("服务器转发:" + message);
}
}
}
// 连接关闭时调用
@OnClose
public void onClose(Session session) {
sessions.remove(session);
System.out.println("连接关闭,当前连接数:" + sessions.size());
}
// 发生错误时调用
@OnError
public void onError(Session session, Throwable error) {
System.err.println("发生错误:" + error.getMessage());
error.printStackTrace();
}
}
2. 客户端代码(HTML/JavaScript)
html
<!DOCTYPE html>
<html>
<head>
<title>WebSocket 客户端</title>
</head>
<body>
<input type="text" id="messageInput" placeholder="输入消息">
<button onclick="sendMessage()">发送</button>
<div id="messageArea"></div>
<script>
// 连接到WebSocket服务器
const ws = new WebSocket('ws://localhost:8080/chat');
// 连接成功时
ws.onopen = function() {
console.log('连接已建立');
};
// 收到消息时
ws.onmessage = function(event) {
const messageArea = document.getElementById('messageArea');
messageArea.innerHTML += '<p>' + event.data + '</p>';
};
// 连接关闭时
ws.onclose = function() {
console.log('连接已关闭');
};
// 发生错误时
ws.onerror = function(error) {
console.error('错误:', error);
};
// 发送消息
function sendMessage() {
const input = document.getElementById('messageInput');
const message = input.value;
if (message && ws.readyState === WebSocket.OPEN) {
ws.send(message);
input.value = '';
}
}
</script>
</body>
</html>

三、部署与运行
-
依赖环境
-
需要支持 Java EE 7 或更高版本的服务器(如 Tomcat 8+、WildFly、GlassFish 等)。
-
Maven 项目需添加 Java WebSocket API 依赖:
XML<dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1</version> <scope>provided</scope> <!-- 服务器通常已内置 --> </dependency>
-
-
部署步骤
- 将服务器端代码打包为 WAR 文件,部署到应用服务器。
- 将客户端 HTML 文件放置在 Web 应用的静态资源目录(如
webapp
下)。 - 启动服务器,访问客户端页面即可测试实时通信。
四、关键 API 详解
-
@ServerEndpoint
标记类为 WebSocket 服务器端点,value
属性指定连接的 URL 路径(如/chat
)。 -
Session
接口getBasicRemote()
:获取同步消息发送器(RemoteEndpoint.Basic
)。getAsyncRemote()
:获取异步消息发送器(RemoteEndpoint.Async
)。isOpen()
:判断连接是否打开。close()
:关闭连接。
-
消息类型 支持文本消息(
String
)、二进制消息(ByteBuffer
或byte[]
)、Pong 消息(心跳响应)等。
五、第三方框架
除了标准 API,还有一些流行的框架简化 WebSocket 开发:
- Spring WebSocket:整合到 Spring 生态,提供更丰富的功能(如 STOMP 协议支持、消息代理等)。
- Netty:高性能网络框架,可用于构建自定义 WebSocket 服务器。
- Undertow:轻量级 Web 服务器,内置对 WebSocket 的支持。
六、应用场景
WebSocket 适用于需要实时通信的场景:
- 即时聊天应用(如在线客服、群聊)。
- 实时数据展示(如股票行情、监控面板)。
- 多人协作工具(如在线文档编辑)。
- 游戏实时交互(如多人在线游戏)。
总结:Java 通过 JSR 356 规范提供了标准化的 WebSocket 支持,结合注解可以快速实现实时通信功能,同时第三方框架进一步扩展了其应用能力。
那么它有什么妙用吗?
WebSocket 在 Java 开发中有着诸多 "妙用",尤其在需要实时性、双向交互的场景中,相比传统的 HTTP 轮询(Polling)或长轮询(Long Polling),能显著提升性能和用户体验。以下是其典型的 "妙用" 场景和技术优势:
1. 实时通讯场景的高效实现
-
即时聊天系统 :无论是单聊、群聊还是在线客服,WebSocket 能在客户端和服务器间建立持久连接,消息到达后可立即推送,避免 HTTP 轮询的频繁请求 / 响应开销。例如:使用 Java 后端 + WebSocket 实现的客服系统,客服发送消息后,用户端能瞬间接收,无需刷新页面。
-
协作编辑工具 :多人同时编辑文档、表格时,WebSocket 可实时同步各方的修改(如光标位置、内容变更),实现 "所见即所得" 的协作体验。技术点 :通过
Session
管理每个用户的连接,使用消息广播机制同步数据。
2. 实时数据监控与推送
-
系统监控面板 :服务器性能指标(CPU 使用率、内存占用)、设备状态(物联网传感器数据)等需要实时更新的场景,WebSocket 可主动向客户端推送最新数据,避免客户端频繁请求。优势:相比轮询,减少无效请求(如数据无变化时),降低服务器压力。
-
金融 / 行情数据 :股票价格、加密货币行情等高频变动的数据,通过 WebSocket 可实现毫秒级更新,确保用户获取实时信息。实现:Java 后端订阅行情数据源,一旦数据更新,立即通过 WebSocket 推送给所有连接的客户端。
3. 游戏实时交互
- 多人在线游戏 :玩家的操作(移动、攻击)需要实时同步到其他玩家客户端,WebSocket 的低延迟特性适合此类场景。优化 :结合二进制消息(
ByteBuffer
)传输游戏数据,减少序列化开销,提升响应速度。
4. 替代轮询,优化性能
传统 HTTP 轮询存在明显缺陷:
- 每次请求需携带完整 HTTP 头,浪费带宽;
- 服务器被动等待请求,无法主动推送;
- 频繁请求导致服务器负载过高。
WebSocket 的优势:
- 持久连接:一次握手后保持连接,减少握手开销;
- 双向通信:服务器可主动推送数据,无需客户端请求;
- 轻量协议:数据帧头部小,传输效率高。
例如:一个实时通知系统,使用 WebSocket 后,服务器在事件发生时(如订单状态变更)可立即推送通知,相比轮询减少 90% 以上的无效请求。
5. 与 Spring 生态结合的高级用法
Spring 提供了对 WebSocket 的增强支持(Spring WebSocket
),扩展出更多 "妙用":
- STOMP 协议支持:在 WebSocket 基础上封装消息格式,支持主题订阅(Topic)、队列(Queue)等,简化群聊、点对点消息等功能实现。
- 消息代理:整合 RabbitMQ、Redis 等,实现分布式环境下的消息广播(如多服务器节点间的客户端消息同步)。
- 安全控制:结合 Spring Security 实现 WebSocket 连接的身份认证和权限校验(如仅允许登录用户建立连接)。
6. 物联网(IoT)设备通信
物联网设备(如智能家电、传感器)需要与服务器实时交互状态或接收指令,WebSocket 可作为轻量级通信层:
- 设备上线后建立 WebSocket 连接,实时上报数据(如温度、湿度);
- 服务器通过连接向设备发送控制指令(如 "开启空调")。优势:相比 MQTT 等协议,WebSocket 更易与 Web 系统集成,适合需要网页端实时监控的场景。
总结
WebSocket 的核心 "妙用" 在于打破了 HTTP 的 "请求 - 响应" 模式,实现了服务器主动推送 和双向实时通信,特别适合对实时性、交互性要求高的场景。在 Java 中,通过 JSR 356 规范或 Spring WebSocket 等框架,开发者可以快速构建高效、低延迟的实时应用,显著提升用户体验和系统性能。