- 使用 Java EE / Jakarta EE 的 API (JSR 356 - Java API for WebSocket):这是 Java 标准自带的 API,无需额外引入核心库,非常规范,如果你的应用服务器(如 Tomcat, Jetty, WildFly)支持 Jakarta EE 8+ 或 Java EE 7+,就可以直接使用。
- 使用 Spring Framework 的 WebSocket 支持:这是在 Spring 生态中最常用、功能最强大的方式,它提供了更高级的抽象、STOMP 协议支持、与 Spring Security 的无缝集成以及更简单的配置方式。
下面我将分别详细介绍这两种实现方式,并提供一个完整的、可运行的 Spring Boot 示例。

使用 Java EE (JSR 356) 标准 API
这种方式更贴近底层,适合理解 WebSocket 协议本身或在非 Spring 环境下开发。
环境准备
- JDK 8+
- 一个支持 WebSocket 的服务器,如 Apache Tomcat 8+ 或 Jetty 9+。
实现步骤
步骤 1:创建 WebSocket 端点
使用 @ServerEndpoint 注解来定义一个 WebSocket 端点,这个类将处理所有 WebSocket 连接的生命周期事件。
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
// @ServerEndpoint 注解定义了一个WebSocket端点
// value 是连接的URL路径
@ServerEndpoint("/websocket/ee")
public class JavaEeWebSocketEndpoint {
// 使用一个静态的 Set 来存储所有连接的会话,实现简单的广播功能
// 注意:在分布式环境下,需要使用更复杂的方式(如Redis Pub/Sub)来管理会话
private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<>());
// 当一个新的WebSocket连接打开时调用
@OnOpen
public void onOpen(Session session) {
System.out.println("WebSocket连接已打开: " + session.getId());
sessions.add(session);
// 可以向客户端发送欢迎消息
try {
session.getBasicRemote().sendText("欢迎连接到 Java EE WebSocket 服务器!");
} catch (IOException e) {
e.printStackTrace();
}
}
// 当客户端发送消息时调用
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("从客户端 " + session.getId() + " 收到消息: " + message);
// 回显消息给发送者
try {
session.getBasicRemote().sendText("服务器回复: " + message);
} catch (IOException e) {
e.printStackTrace();
}
}
// 当WebSocket连接关闭时调用
@OnClose
public void onClose(Session session) {
System.out.println("WebSocket连接已关闭: " + session.getId());
sessions.remove(session);
}
// 当发生错误时调用
@OnError
public void onError(Throwable error, Session session) {
System.err.println("WebSocket发生错误: " + session.getId());
error.printStackTrace();
sessions.remove(session);
}
// (可选) 一个简单的广播方法
public static void broadcast(String message) {
sessions.forEach(session -> {
try {
if (session.isOpen()) {
session.getBasicRemote().sendText(message);
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
步骤 2:部署到服务器

将你的 Web 应用(一个 WAR 文件)部署到 Tomcat 或 Jetty 服务器上。
步骤 3:创建前端 HTML 页面
在 Web 应用的 webapp 目录下创建一个 index.html 文件来测试。
<!DOCTYPE html>
<html>
<head>Java EE WebSocket 客户端</title>
</head>
<body>
<h2>Java EE WebSocket 聊天</h2>
<div id="messages"></div>
<input type="text" id="messageInput">
<button onclick="sendMessage()">发送</button>
<script>
var socket = new WebSocket('ws://' + window.location.host + '/your-webapp-context/websocket/ee');
socket.onopen = function(event) {
console.log('连接已建立!');
document.getElementById('messages').innerHTML += '<p>连接成功!</p>';
};
socket.onmessage = function(event) {
console.log('收到消息: ' + event.data);
document.getElementById('messages').innerHTML += '<p>' + event.data + '</p>';
};
socket.onclose = function(event) {
console.log('连接已关闭.');
document.getElementById('messages').innerHTML += '<p>连接已关闭.</p>';
};
socket.onerror = function(error) {
console.error('WebSocket错误: ' + error);
};
function sendMessage() {
var input = document.getElementById('messageInput');
if (socket.readyState === WebSocket.OPEN) {
socket.send(input.value);
input.value = '';
} else {
alert('连接未建立,无法发送消息!');
}
}
</script>
</body>
</html>
注意:将 your-webapp-context 替换成你的实际 Web 应用上下文路径。

使用 Spring Framework (推荐)
Spring 对 WebSocket 的封装非常出色,配置简单,功能强大,是目前企业级应用开发的首选。
环境准备
- JDK 8+
- Spring Boot 2.x (推荐,因为它极大地简化了配置)
实现步骤
步骤 1:添加 Maven 依赖
在 pom.xml 中添加 spring-boot-starter-websocket 依赖。
<dependencies>
<!-- Spring Boot WebSocket 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 用于构建前端页面的 Thymeleaf 模板引擎 (可选) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
步骤 2:配置 WebSocket
创建一个配置类来启用并注册 WebSocket。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket // 启用 WebSocket 支持
public class WebSocketConfig implements WebSocketConfigurer {
// 注入我们自定义的 WebSocket 处理器
// @Autowired
// private MyWebSocketHandler myWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册 WebSocket 处理器,并指定 WebSocket 端点
// .setAllowedOrigins("*") 允许所有来源连接,生产环境请根据需要配置
registry.addHandler(new MyWebSocketHandler(), "/websocket/spring")
.setAllowedOrigins("*");
}
}
步骤 3:创建 WebSocket 处理器
这个类负责处理具体的 WebSocket 事件,类似于 JSR 356 中的 Endpoint 类。
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class MyWebSocketHandler extends TextWebSocketHandler {
// 使用 ConcurrentHashMap 来存储所有连接的会话,线程安全
private static final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
// 连接建立后
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("新连接建立: " + session.getId());
sessions.put(session.getId(), session);
// 向新连接的客户端发送欢迎消息
session.sendMessage(new TextMessage("欢迎连接到 Spring WebSocket 服务器!"));
}
// 收到消息后
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
System.out.println("从客户端 " + session.getId() + " 收到消息: " + payload);
// 回显消息给发送者
session.sendMessage(new TextMessage("服务器回复: " + payload));
// (可选) 广播消息给所有连接的客户端
// broadcast("广播消息: " + payload);
}
// 连接关闭后
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("连接关闭: " + session.getId() + ", 原因: " + status);
sessions.remove(session.getId());
}
// (可选) 广播方法
public void broadcast(String message) {
sessions.forEach((id, session) -> {
try {
if (session.isOpen()) {
session.sendMessage(new TextMessage(message));
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
步骤 4:创建前端页面
在 src/main/resources/templates 目录下创建 index.html (如果使用了 Thymeleaf)。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>Spring WebSocket 客户端</title>
</head>
<body>
<h2>Spring WebSocket 聊天</h2>
<div id="messages"></div>
<input type="text" id="messageInput">
<button onclick="sendMessage()">发送</button>
<script th:inline="javascript">
// 获取当前应用的上下文路径
var contextPath = /*[[${#request.contextPath}]]*/ '';
// 构建完整的 WebSocket URL
var socket = new WebSocket('ws://' + window.location.host + contextPath + '/websocket/spring');
socket.onopen = function(event) {
console.log('连接已建立!');
document.getElementById('messages').innerHTML += '<p>连接成功!</p>';
};
socket.onmessage = function(event) {
console.log('收到消息: ' + event.data);
document.getElementById('messages').innerHTML += '<p>' + event.data + '</p>';
};
socket.onclose = function(event) {
console.log('连接已关闭.');
document.getElementById('messages').innerHTML += '<p>连接已关闭.</p>';
};
socket.onerror = function(error) {
console.error('WebSocket错误: ' + error);
};
function sendMessage() {
var input = document.getElementById('messageInput');
if (socket.readyState === WebSocket.OPEN) {
socket.send(input.value);
input.value = '';
} else {
alert('连接未建立,无法发送消息!');
}
}
</script>
</body>
</html>
步骤 5:创建主启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebSocketApplication {
public static void main(String[] args) {
SpringApplication.run(WebSocketApplication.class, args);
}
}
运行 WebSocketApplication,然后访问 http://localhost:8080,你就可以在浏览器中测试 WebSocket 连接了。
总结与对比
| 特性 | Java EE (JSR 356) | Spring Framework |
|---|---|---|
| 依赖 | 无需额外核心库,依赖应用服务器 | 需要 spring-boot-starter-websocket |
| 配置 | 通过注解直接在类上配置 | 需要一个独立的 @Configuration 类 |
| 易用性 | 较为底层,需要手动管理会话集 | Spring 自动管理,集成度高,非常方便 |
| 功能 | 标准功能,支持点对点和广播 | 标准功能 + STOMP 协议支持、Socks5、与 Spring Security/集成等高级特性 |
| 适用场景 | 学习协议、轻量级应用、非 Spring 项目 | 强烈推荐,任何基于 Spring Boot/Spring MVC 的项目,尤其是需要复杂功能(如聊天室、实时通知)的项目 |
对于新的项目,尤其是使用 Spring Boot 的项目,强烈推荐使用方式二(Spring Framework),它提供了更优雅的编程模型、更强大的功能和更好的可维护性,Java EE API 虽然标准,但在实际开发中显得有些“原始”。
