Java中使用WebSocket(Tyrus)如何从外部类调用服务端端点方法?
Tyrus WebSocket服务器:外部类与ServerEndpoint交互及广播实现
当然可以让程序里的其他类和你的ExampleServerEndpoint交互,不过得先搞清楚Tyrus的核心机制:每个WebSocket客户端连接都会创建一个全新的ExampleServerEndpoint实例。所以直接实例化这个类调用方法是没用的——你得先把所有活跃的连接会话(Session)统一管理起来,才能实现全局广播或者其他交互。
下面给你具体的实现方案:
第一步:改造ServerEndpoint,统一管理活跃Session
修改ExampleServerEndpoint,用线程安全的静态集合保存所有打开的Session,同时实现广播逻辑:
@ServerEndpoint(value = "/example") public class ExampleServerEndpoint { // 线程安全的集合,存储所有当前活跃的WebSocket会话 private static final Set<Session> activeSessions = Collections.synchronizedSet(new HashSet<>()); @OnOpen public void onOpen(Session session) { activeSessions.add(session); System.out.println("新连接上线:" + session.getId()); } @OnMessage public void onMessage(String message, Session session) { // 收到客户端消息时,直接广播给所有人 broadcast(message); } @OnClose public void onClose(Session session, CloseReason closeReason) { activeSessions.remove(session); System.out.println("连接关闭:" + session.getId() + ",原因:" + closeReason.getReasonPhrase()); } @OnError public void onError(Session session, Throwable throwable) { System.err.println("连接出错:" + session.getId()); throwable.printStackTrace(); activeSessions.remove(session); } // 内部广播方法,遍历所有活跃会话发送消息 private void broadcast(String message) { for (Session session : activeSessions) { if (session.isOpen()) { // 先检查会话是否还处于打开状态 try { session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } } // 对外暴露的静态广播方法,让外部类可以直接调用 public static void broadcastFromExternal(String message) { new ExampleServerEndpoint().broadcast(message); } }
第二步:在外部类中调用Endpoint的功能
现在你的WebsocketServer或者其他任意类,都可以通过静态方法触发广播了。比如给WebsocketServer加一个广播方法:
public class WebsocketServer{ private int port; private Server server; public WebsocketServer(int port) { this.port = port; server = new Server("localhost", this.port, "/websockets", ExampleServerEndpoint.class); } public void startServer() throws Exception{ server.start(); System.out.println("WebSocket服务器已启动,端口:" + port); } public void stopServer() throws Exception{ server.stop(); } // 新增方法:让外部可以通过Server实例触发全局广播 public void sendBroadcast(String message) { ExampleServerEndpoint.broadcastFromExternal(message); } }
关键注意点
- 线程安全问题:一定要用线程安全的集合(比如
Collections.synchronizedSet),因为WebSocket的回调方法(OnOpen/OnClose等)是在不同线程执行的,并发修改集合会出问题。 - 会话有效性检查:发送消息前必须调用
session.isOpen(),避免向已经关闭的会话发送消息抛出异常。 - 扩展场景:如果需要给特定用户发送消息,可以在
OnOpen时给Session绑定用户标识(比如session.getUserProperties().put("userId", "123")),然后在广播时筛选符合条件的Session即可。
内容的提问来源于stack exchange,提问作者captain_janitor
相关产品推荐
相关产品推荐

