如何通过main()方法部署Jakarta WebSocket @ServerEndpoint类
问题:如何通过Main.java启动Jakarta WebSocket服务器并部署端点
我在网上未找到Jakarta仓库中关于部署WebSocket端点的有效文档,端点不部署无法发挥作用。我已编写WebSocket服务器端点代码,但不知道如何通过Main.java启动监听,目标是像我的WebSocket客户端那样,用Main.java直接启动服务器。
现有WebSocket服务器端点代码
package com.wsserver; import java.io.IOException; import jakarta.websocket.*; import jakarta.websocket.server.ServerEndpoint; @ServerEndpoint("/ws") public class WebSocketEndpoint { @OnOpen public void onOpen(Session session) { System.out.println("WebSocket opened: " + session.getId()); } @OnMessage public void onMessage(String message, Session session) { System.out.println("Message received: " + message); try { session.getBasicRemote().sendText("Echo: " + message); } catch (IOException e) { e.printStackTrace(); } } @OnClose public void onClose(Session session, CloseReason closeReason) { System.out.println("WebSocket closed: " + session.getId()); } @OnError public void onError(Session session, Throwable throwable) { System.out.println("WebSocket error: " + session.getId()); throwable.printStackTrace(); } }
现有Main.java代码(存在问题)
package com.wsserver; import jakarta.websocket.ContainerProvider; import jakarta.websocket.OnClose; import jakarta.websocket.OnMessage; import jakarta.websocket.OnClose; import jakarta.websocket.OnError; import jakarta.websocket.Session; import jakarta.websocket.WebSocketContainer; import jakarta.websocket.server.ServerEndpoint; import jakarta.websocket.server.ServerEndpointConfig; import java.net.URI; import java.net.http.WebSocket; @ServerEndpoint("/ws") public class Main { public static void main(String[] args) throws Exception { ServerEndpointConfig serverEndpoint = ServerEndpointConfig.Builder.create(WebsocketEndpoint.class, "/pathToRoot/").build(); } }
服务器pom.xml配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wsserver</groupId> <artifactId>server</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <!-- Jackson相关 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.18.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.18.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.18.2</version> </dependency> <!-- Jakarta WebSocket API --> <dependency> <groupId>jakarta.websocket</groupId> <artifactId>jakarta.websocket-api</artifactId> <version>2.2.0</version> <scope>provided</scope> </dependency> <!-- Gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.11.0</version> </dependency> <!-- Jakarta WebSocket Client API --> <dependency> <groupId>jakarta.websocket</groupId> <artifactId>jakarta.websocket-client-api</artifactId> <version>2.2.0</version> <scope>provided</scope> </dependency> <!-- Tyrus Standalone Client --> <dependency> <groupId>org.glassfish.tyrus.bundles</groupId> <artifactId>tyrus-standalone-client</artifactId> <version>2.2.0</version> </dependency> <!-- JSON --> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20241224</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.1.0</version> </dependency> </dependencies> </project>
可正常运行的WebSocket客户端代码
客户端端点代码
package com.wsclient; import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; import jakarta.websocket.ClientEndpoint; import jakarta.websocket.CloseReason; import jakarta.websocket.ContainerProvider; import jakarta.websocket.OnClose; import jakarta.websocket.OnMessage; import jakarta.websocket.OnOpen; import jakarta.websocket.Session; import jakarta.websocket.WebSocketContainer; @ClientEndpoint public class WebsocketClientEndpoint { Session userSession = null; private MessageHandler messageHandler; public WebsocketClientEndpoint(URI endpointURI) { try { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); container.connectToServer(this, endpointURI); } catch (Exception e) { throw new RuntimeException(e); } } @OnOpen public void onOpen(Session userSession) { System.out.println("opening websocket"); this.userSession = userSession; } @OnClose public void onClose(Session userSession, CloseReason reason) { System.out.println("closing websocket"); this.userSession = null; } @OnMessage public void onMessage(String message) throws IOException { if (this.messageHandler != null) { this.messageHandler.handleMessage(message); } } @OnMessage public void onMessage(ByteBuffer bytes) { System.out.println("Handle byte buffer"); } public void addMessageHandler(MessageHandler msgHandler) { this.messageHandler = msgHandler; } public void sendMessage(String message) { this.userSession.getAsyncRemote().sendText(message); } public static interface MessageHandler { public void handleMessage(String message) throws IOException; } }
客户端Main.java代码
package com.wsclient; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class Main { public static void main(String[] args) throws Exception { try { // 连接WebSocket服务器 final WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint(new URI("wss://somedomain.com/ws")); clientEndPoint.addMessageHandler( new WebsocketClientEndpoint.MessageHandler() { public void handleMessage(String packet) { System.out.println(packet); } } ); clientEndPoint.sendMessage(payload); // 保持客户端运行 while (true) { Thread.sleep(1000); } } catch (Exception e) { e.printStackTrace(); } } }
客户端pom.xml配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>rtw</groupId> <artifactId>rtw</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <!-- Jackson相关 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.18.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.18.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.18.2</version> </dependency> <!-- Jakarta WebSocket API --> <dependency> <groupId>jakarta.websocket</groupId> <artifactId>jakarta.websocket-api</artifactId> <version>2.2.0</version> <scope>provided</scope> </dependency> <!-- Gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.11.0</version> </dependency> <!-- Jakarta WebSocket Client API --> <dependency> <groupId>jakarta.websocket</groupId> <artifactId>jakarta.websocket-client-api</artifactId> <version>2.2.0</version> <scope>provided</scope> </dependency> <!-- Tyrus Standalone Client --> <dependency> <groupId>org.glassfish.tyrus.bundles</groupId> <artifactId>tyrus-standalone-client</artifactId> <version>2.2.0</version> </dependency> <!-- JSON --> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20241224</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>9.1.0</version> </dependency> </dependencies> </project>
解决方案
Jakarta WebSocket仅提供标准API,需要依赖具体实现(如Tyrus,GlassFish官方的WebSocket参考实现)来启动独立服务器。
步骤1:修改服务器pom.xml,添加Tyrus服务器依赖
移除原有的tyrus-standalone-client,替换为Tyrus服务器相关依赖:
<!-- Tyrus Server核心依赖 --> <dependency> <groupId>org.glassfish.tyrus</groupId> <artifactId>tyrus-server</artifactId> <version>2.2.0</version> </dependency> <!-- Grizzly容器,用于启动服务器监听端口 --> <dependency> <groupId>org.glassfish.tyrus</groupId> <artifactId>tyrus-container-grizzly</artifactId> <version>2.2.0</version> </dependency>
步骤2:重写Main.java,启动Tyrus服务器
删除原错误代码,替换为以下内容,直接启动服务器并注册端点:
package com.wsserver; import org.glassfish.tyrus.server.Server; public class Main { public static void main(String[] args) { // 定义服务器监听地址和端口 String host = "localhost"; int port = 8080; // 创建Tyrus服务器,指定端点类 Server server = new Server(host, port, "/", null, WebSocketEndpoint.class); try { // 启动服务器 server.start(); System.out.println("WebSocket服务器已启动,连接地址:ws://" + host + ":" + port + "/ws"); // 阻塞主线程,保持服务器运行,按回车停止 System.out.println("按回车键停止服务器..."); System.in.read(); } catch (Exception e) { throw new RuntimeException(e); } finally { // 停止服务器 server.stop(); } } }
步骤3:修正类名拼写问题
原Main.java中误写的WebsocketEndpoint(小写s)已修正为实际类名WebSocketEndpoint(大写S)。
测试验证
- 运行服务器Main.java,控制台会输出服务器启动信息。
- 修改客户端Main.java的连接地址为
ws://localhost:8080/ws,启动客户端。 - 客户端发送消息后,服务器会返回
Echo: [消息内容],双方控制台均能看到对应日志。
关键说明
- 独立WebSocket服务器必须依赖具体实现,Jakarta API本身不包含服务器运行时。
- Tyrus的
Server类负责启动监听端口,并自动扫描注册带有@ServerEndpoint注解的端点类。 - 服务器启动后需保持主线程不退出,这里用
System.in.read()阻塞主线程,避免程序直接终止。
内容的提问来源于stack exchange,提问作者thegillionaire
相关产品推荐
相关产品推荐

