引言:为什么 WebSocket 是 Java 实时应用的标准
现代 Web 应用要求客户端与服务器之间进行即时数据交换。传统的基于"请求-响应"模型的 HTTP 协议,对于需要极低延迟的场景(如在线聊天、股票行情、多人在线游戏或实时监控面板)并不理想。
WebSocket 协议通过建立客户端与服务器之间的持久双向连接解决了这一问题。在初始 HTTP 握手之后,连接"升级"为 WebSocket,数据以帧的形式传输,无需额外头部信息。Java 凭借其强大的标准库和框架,为使用 WebSocket 提供了出色的工具。
在本文中,我们将探讨如何使用 Jakarta WebSocket API(原 Java EE WebSocket)在 Java 中构建一个完整的实时应用。您将了解服务器配置、消息处理、会话管理以及典型的架构设计模式。
Java 中 WebSocket 的基础知识:Jakarta WebSocket API
从 Java EE 7(Jakarta EE)开始,标准平台中加入了 JSR 356——Java WebSocket API。这意味着创建 WebSocket 服务器无需引入第三方库,只需一个支持 Jakarta EE 的 Servlet 容器(例如 Apache Tomcat 9+、Jetty 10+、WildFly)即可。
创建 WebSocket 端点
核心元素是一个使用 @ServerEndpoint 注解的端点类。在该类中,我们定义在连接建立、收到消息、发生错误或连接关闭时调用的方法。
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint("/chat")
public class ChatEndpoint {
private static final Set<Session> sessions = new CopyOnWriteArraySet<>();
@OnOpen
public void onOpen(Session session) {
sessions.add(session);
broadcast("用户已连接。当前在线:" + sessions.size());
}
@OnMessage
public void onMessage(String message, Session session) {
broadcast("[" + session.getId() + "]: " + message);
}
@OnClose
public void onClose(Session session) {
sessions.remove(session);
broadcast("用户已断开。剩余:" + sessions.size());
}
@OnError
public void onError(Session session, Throwable throwable) {
System.err.println("会话 " + session.getId() + " 发生错误:" + throwable.getMessage());
}
private void broadcast(String message) {
for (Session s : sessions) {
if (s.isOpen()) {
try {
s.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
在此示例中:
@ServerEndpoint("/chat")— 指定端点可通过相对路径/chat访问。CopyOnWriteArraySet— 用于存储活动会话的线程安全集合。@OnOpen— 在建立连接时调用。@OnMessage— 在收到文本消息时调用。@OnClose— 在连接关闭时调用。@OnError— 错误处理。
客户端 JavaScript
只需一个包含 JavaScript 的简单 HTML 文件即可测试服务器:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Chat</title>
</head>
<body>
<div id="messages"></div>
<input type="text" i