在 Java 生态中,实现 WebSocket 客户端主要有两种主流方式:

- Java-WebSocket (推荐): 这是一个轻量级、纯 Java 实现的 WebSocket 客户端和服务器库,它非常流行,易于使用,是大多数 Java 项目的首选。
- Jakarta WebSocket (JSR-356): 这是 Java EE / Jakarta EE 标准的一部分,如果你的项目是基于 Jakarta EE 的(在 Jakarta EE 容器中运行的客户端),或者你需要与 Jakarta WebSocket 服务器兼容,那么应该使用这个标准 API。
下面我将分别介绍这两种方式,并提供完整的示例代码。
使用 Java-WebSocket 库 (推荐)
这是最简单、最直接的方式,特别适合独立的 Java 应用程序(如命令行工具、桌面应用或非 Jakarta EE 的后端服务)。
添加依赖
你需要将 Java-WebSocket 库添加到你的项目中。
Maven (pom.xml)

<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.5</version> <!-- 请使用最新版本 -->
</dependency>
Gradle (build.gradle)
implementation 'org.java-websocket:Java-WebSocket:1.5.5' // 请使用最新版本
创建客户端类
Java-WebSocket 提供了一个 WebSocketClient 类,你可以继承它并重写关键方法来处理 WebSocket 生命周期事件。
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
public class MyWebSocketClient extends WebSocketClient {
public MyWebSocketClient(URI serverUri) {
super(serverUri);
}
/**
* 连接建立时调用
*/
@Override
public void onOpen(ServerHandshake handshakedata) {
System.out.println("连接已建立!");
// 连接成功后,可以立即发送消息
send("Hello, Server! This is a message from the client.");
}
/**
* 收到服务器消息时调用
*/
@Override
public void onMessage(String message) {
System.out.println("收到消息: " + message);
}
/**
* 连接关闭时调用
*/
@Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("连接已关闭!");
System.out.println("关闭原因: " + reason);
System.out.println("是否由远程端关闭: " + remote);
}
/**
* 发生错误时调用
*/
@Override
public void onError(Exception ex) {
System.err.println("发生错误:");
ex.printStackTrace();
}
}
启动客户端
创建一个主类来实例化并启动我们的客户端。
import java.net.URI;
public class WebSocketClientApp {
public static void main(String[] args) {
// 替换成你的 WebSocket 服务器地址
String serverUrl = "ws://echo.websocket.events"; // 一个公共的测试 WebSocket 服务器
URI serverUri = URI.create(serverUrl);
MyWebSocketClient client = new MyWebSocketClient(serverUri);
// 添加关闭钩子,确保程序退出时能正确关闭连接
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
if (client.isOpen()) {
client.close();
}
}));
// 连接到服务器
client.connect();
System.out.println("客户端正在尝试连接到: " + serverUrl);
System.out.println("等待连接...");
// 为了保持主线程存活,让客户端能持续接收消息
try {
Thread.sleep(30000); // 运行30秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭连接
System.out.println("30秒已到,关闭连接。");
client.close();
}
}
运行结果
当你运行 WebSocketClientApp 时,你会看到类似以下的输出:

客户端正在尝试连接到: ws://echo.websocket.events
等待连接...
连接已建立!
收到消息: Hello, Server! This is a message from the client.
... (服务器会回显你发送的消息)
30秒已到,关闭连接。
连接已关闭!
关闭原因: Closing
是否由远程端关闭: true
使用 Jakarta WebSocket (JSR-356) API
这是官方标准,如果你的项目是基于 Jakarta EE 的(在 Tomcat, WildFly 等服务器上运行),或者你希望代码更具可移植性,应该使用这种方式。
添加依赖
你需要包含 Jakarta WebSocket API 和一个实现它的服务器的客户端库,如果你使用 Tomcat,你需要添加 jakarta.websocket-api 和 tomcat-websocket。
Maven (pom.xml)
<!-- Jakarta WebSocket API -->
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<version>2.1.1</version> <!-- 使用与你的 Jakarta EE 版本匹配的版本 -->
</dependency>
<!-- Tomcat 实现的客户端库 -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-websocket</artifactId>
<version>10.1.15</version> <!-- 版本号应与 Tomcat 版本对应 -->
</dependency>
创建客户端端点
在 Jakarta WebSocket 中,你通过一个带有 @ClientEndpoint 注解的 POJO (Plain Old Java Object) 来定义客户端行为。
import jakarta.websocket.*;
import java.net.URI;
@ClientEndpoint
public class JakartaWebSocketClient {
private Session session;
private WebSocketContainer container;
public JakartaWebSocketClient() {
// WebSocketContainer 是 Jakarta WebSocket API 的入口点
this.container = ContainerProvider.getWebSocketContainer();
}
public void connect(String uri) throws DeploymentException, java.io.IOException {
// 连接到服务器
session = container.connectToServer(this, URI.create(uri));
System.out.println("连接已建立!");
}
/**
* 当连接打开时由容器调用
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
try {
// 发送初始消息
session.getBasicRemote().sendText("Hello, Server! This is a Jakarta WebSocket client.");
} catch (Exception 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("连接已关闭!");
System.out.println("关闭原因: " + closeReason);
}
/**
* 当发生错误时由容器调用
*/
@OnError
public void onError(Session session, Throwable thr) {
System.err.println("发生错误:");
thr.printStackTrace();
}
/**
* 发送消息的方法
*/
public void sendMessage(String message) throws IOException {
if (session != null && session.isOpen()) {
session.getBasicRemote().sendText(message);
} else {
System.out.println("会话未打开,无法发送消息。");
}
}
/**
* 关闭连接
*/
public void close() throws IOException {
if (session != null && session.isOpen()) {
session.close();
}
}
}
启动客户端
创建一个主类来使用这个客户端端点。
import jakarta.websocket.DeploymentException;
import java.io.IOException;
import java.net.URI;
public class JakartaWebSocketClientApp {
public static void main(String[] args) {
String serverUrl = "ws://echo.websocket.events"; // 同样使用公共测试服务器
JakartaWebSocketClient client = new JakartaWebSocketClient();
try {
// 连接服务器
client.connect(serverUrl);
// 保持主线程存活
Thread.sleep(30000); // 运行30秒
// 关闭连接
System.out.println("30秒已到,关闭连接。");
client.close();
} catch (DeploymentException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
总结与对比
| 特性 | Java-WebSocket | Jakarta WebSocket (JSR-356) |
|---|---|---|
| 类型 | 第三方库 | 官方标准 |
| 依赖 | 只需一个 Java-WebSocket JAR |
需要 API JAR + 特定服务器的实现 JAR (如 Tomcat, WildFly) |
| 易用性 | 非常简单,继承 WebSocketClient 即可 |
使用注解 (@ClientEndpoint, @OnOpen 等),更面向对象 |
| 适用场景 | 独立应用、快速原型、任何 Java 环境 | Jakarta EE 应用、需要标准 API 的项目、追求可移植性 |
| 灵活性 | API 设计更直接,底层控制感强 | 标准化,但可能受限于具体实现 |
| 推荐度 | 对于大多数 Java 这是首选 | 如果你的项目环境已经是 Jakarta EE,那么它是自然的选择 |
如何选择?
- 如果你正在编写一个简单的 Java 应用、一个工具或者一个非 Jakarta EE 的后端服务,毫不犹豫地选择
Java-WebSocket,它更轻量,引入的依赖更少。 - 如果你的项目运行在 Jakarta EE 容器中(一个 Jakarta EE 微服务),或者你的团队坚持使用标准 API,那么使用
Jakarta WebSocket是正确的做法。
希望这个详细的指南能帮助你理解和使用 Java WebSocket 客户端!
