核心概念
在开始之前,先明确几个关键点:

- WebSocket 协议:一种在单个 TCP 连接上进行全双工通信的协议,客户端和服务器可以随时相互推送数据。
- Java 内置 API (
java-websocket):Java 标准库中没有直接包含 WebSocket 客户端,最常用、最标准的“准官方”实现是 TooTallNate/Java-WebSocket,它通常被认为是 Java WebSocket 的“内置”或“标准”选择。 - 异步 vs. 同步:WebSocket 通信本质上是异步的,数据到达时,会触发一个回调事件,而不是像普通 HTTP 请求那样阻塞线程等待响应。
- 连接生命周期:客户端需要处理连接的开启、消息接收、错误发生和连接关闭等事件。
使用 java-websocket (最常用、推荐)
这是最流行和成熟的 Java WebSocket 客户端库,它轻量级、稳定,并且是许多其他框架的基础。
添加 Maven 依赖
在你的 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.5</version> <!-- 建议使用最新版本 -->
</dependency>
创建一个简单的 WebSocket 客户端
下面是一个完整的、可运行的客户端示例,它连接到一个公共的 WebSocket 测试服务器(ws://echo.websocket.org),发送一条消息,并打印收到的响应。
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.net.URISyntaxException;
public class SimpleWebSocketClient {
public static void main(String[] args) {
try {
// 创建一个 WebSocketClient 实例
// 注意:URI 必须以 "ws://" (WebSocket) 或 "wss://" (WebSocket Secure) 开头
WebSocketClient webSocketClient = new WebSocketClient(new URI("ws://echo.websocket.org")) {
@Override
public void onOpen(ServerHandshake handshakedata) {
System.out.println("连接已建立!");
// 连接成功后,可以发送消息
this.send("Hello, WebSocket Server!");
}
@Override
public void onMessage(String message) {
// 收到服务器发来的消息
System.out.println("收到消息: " + message);
}
@Override
public void onClose(int code, String reason, boolean remote) {
// 连接关闭时触发
// remote=true 表示是服务器关闭的连接,false 表示是客户端关闭的
System.out.println("连接已关闭! Code: " + code + ", Reason: " + reason);
}
@Override
public void onError(Exception ex) {
// 发生错误时触发
System.err.println("发生错误:");
ex.printStackTrace();
}
};
// 连接服务器
webSocketClient.connect();
// 为了保持程序运行,以便接收消息
// 在真实应用中,你可能需要一个更健壮的生命周期管理
try {
Thread.sleep(10000); // 等待10秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭连接
System.out.println("主动关闭连接...");
webSocketClient.close();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
代码解析
WebSocketClient: 这是核心类,你需要继承它并重写几个关键方法。onOpen(ServerHandshake handshakedata): 当 WebSocket 连接成功建立时,此方法被调用,这是发送第一条消息的好地方。onMessage(String message): 当从服务器接收到文本消息时,此方法被调用。message参数就是服务器发送的内容。onClose(int code, String reason, boolean remote): 当连接关闭时调用。code是关闭状态码,reason是关闭原因,remote指示关闭是由客户端还是服务器发起的。onError(Exception ex): 在连接或通信过程中发生错误时调用。connect(): 异步方法,用于启动连接过程。send(String message): 向服务器发送文本消息。close(): 关闭 WebSocket 连接。
使用 Spring WebSocket (适用于 Spring 应用)
如果你的项目是基于 Spring Framework 的,那么使用 Spring 的 WebSocket 支持会是更自然、更集成的选择。

添加 Maven 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.3.23</version> <!-- 使用与你的 Spring 版本兼容的最新版本 -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>5.3.23</version>
</dependency>
创建 WebSocket 客户端端点
Spring 提供了 @ClientEndpoint 注解来简化客户端的创建。
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
@Component
@ClientEndpoint
public class SpringWebSocketClient {
private Session session;
private final CountDownLatch latch = new CountDownLatch(1);
@OnOpen
public void onOpen(Session session) {
System.out.println("连接已建立!");
this.session = session;
latch.countDown(); // 通知连接已建立
try {
// 发送消息
session.getBasicRemote().sendText("Hello from Spring WebSocket Client!");
} catch (IOException e) {
e.printStackTrace();
}
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("收到消息: " + message);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("连接已关闭! Reason: " + closeReason);
}
@OnError
public void onError(Session session, Throwable throwable) {
System.err.println("发生错误:");
throwable.printStackTrace();
}
public void sendMessage(String message) throws IOException {
if (this.session != null && this.session.isOpen()) {
this.session.getBasicRemote().sendText(message);
}
}
public void connect(String uri) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, new URI(uri));
}
public void disconnect() throws IOException {
if (this.session != null && this.session.isOpen()) {
this.session.close();
}
}
public static void main(String[] args) throws Exception {
SpringWebSocketClient client = new SpringWebSocketClient();
client.connect("ws://echo.websocket.org");
// 等待连接建立
client.latch.await();
// 发送第二条消息
client.sendMessage("This is the second message.");
// 等待一段时间以便接收消息
Thread.sleep(5000);
// 关闭连接
client.disconnect();
}
}
代码解析
@ClientEndpoint: 将一个类标记为 WebSocket 客户端端点。@OnOpen,@OnMessage,@OnClose,@OnError: 这些注解将方法与 WebSocket 生命周期事件关联起来,与java-websocket的回调方法类似。Session: 代表一个 WebSocket 会话,用于发送消息和获取会话信息。ContainerProvider.getWebSocketContainer().connectToServer(...): 这是启动连接的标准方式。getBasicRemote().sendText(...): 用于发送文本消息。
使用 Tyrus (Java EE 标准)
Tyrus 是 Java WebSocket (JSR-356) 的参考实现,通常用在 Java EE (如 Jakarta EE) 或支持 Servlet 3.1+ 的容器中。
添加 Maven 依赖
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
<version>2.1.3</version> <!-- 使用最新版本 -->
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly</artifactId>
<version>2.1.3</version>
</dependency>
创建客户端
Tyrus 的客户端 API 与 Spring 的 @ClientEndpoint 非常相似,因为它们都遵循 JSR-356 规范。
import javax.websocket.*;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
@ClientEndpoint
public class TyrusWebSocketClient {
private Session session;
private final CountDownLatch latch = new CountDownLatch(1);
@OnOpen
public void onOpen(Session session) {
System.out.println("Tyrus: 连接已建立!");
this.session = session;
latch.countDown();
try {
session.getBasicRemote().sendText("Hello from Tyrus Client!");
} catch (IOException e) {
e.printStackTrace();
}
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Tyrus: 收到消息: " + message);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("Tyrus: 连接已关闭! Reason: " + closeReason);
}
@OnError
public void onError(Session session, Throwable throwable) {
System.err.println("Tyrus: 发生错误:");
throwable.printStackTrace();
}
public void sendMessage(String message) throws IOException {
if (this.session != null && this.session.isOpen()) {
this.session.getBasicRemote().sendText(message);
}
}
public void connect(String uri) throws Exception {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, new URI(uri));
}
public static void main(String[] args) throws Exception {
TyrusWebSocketClient client = new TyrusWebSocketClient();
client.connect("ws://echo.websocket.org");
client.latch.await();
client.sendMessage("This is a message from Tyrus.");
Thread.sleep(5000);
// Tyrus 没有显式的 disconnect 方法,关闭 session 即可
if (client.session != null && client.session.isOpen()) {
client.session.close();
}
}
}
总结与选择建议
| 特性 | java-websocket (TooTallNate) |
Spring WebSocket | Tyrus (JSR-356) |
|---|---|---|---|
| 易用性 | 简单直接,继承即可 | 非常集成,与 Spring 生态无缝对接 | 标准规范,注解清晰 |
| 依赖 | 轻量级,单一库 | 需要 Spring 框架 | 需要 Tyrus 库和容器 |
| 适用场景 | 独立 Java 应用,小型项目 | 基于 Spring 的所有项目 | Java EE/Jakarta EE 应用,遵循标准 |
| 功能 | 核心功能完备 | 提供与 Spring MVC 集成的高级功能 | 标准功能,兼容性好 |
| 推荐度 | ⭐⭐⭐⭐⭐ (通用首选) | ⭐⭐⭐⭐⭐ (Spring 项目首选) | ⭐⭐⭐⭐ (标准项目首选) |
如何选择?

- 如果你只是想在 Java 程序里快速实现一个 WebSocket 客户端,并且不想引入庞大的框架,
java-websocket是你的最佳选择,它简单、高效、文档齐全。 - 如果你的项目已经使用了 Spring Boot 或 Spring Framework,毫无疑问应该使用 Spring WebSocket,它能更好地与其他 Spring 组件(如 Security, MVC)集成,管理起来更方便。
- 如果你正在开发一个 Java EE 应用,或者希望代码严格遵循 Java 标准,Tyrus 是一个很好的选择,它保证了代码的可移植性。
希望这份详细的指南能帮助你顺利地在 Java 中使用 WebSocket 客户端!
