杰瑞科技汇

Java WebSocket客户端如何实现?

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

Java WebSocket客户端如何实现?-图1
(图片来源网络,侵删)
  1. Java-WebSocket (推荐): 这是一个轻量级、纯 Java 实现的 WebSocket 客户端和服务器库,它非常流行,易于使用,是大多数 Java 项目的首选。
  2. 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)

Java WebSocket客户端如何实现?-图2
(图片来源网络,侵删)
<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 时,你会看到类似以下的输出:

Java WebSocket客户端如何实现?-图3
(图片来源网络,侵删)
客户端正在尝试连接到: 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-apitomcat-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 客户端!

分享:
扫描分享到社交APP
上一篇
下一篇