You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:33:10