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

如何在Java WebSocket(Jetty环境)中实现服务端主动发消息

如何让Jetty WebSocket服务端主动向客户端发送消息

我来帮你搞定这个问题!你当前的代码核心缺失是没有管理客户端的Session——这可是服务端主动发消息的关键,因为Session就是服务端和单个客户端之间的专属通信通道。下面是一步步的实现方案:

1. 修改服务端代码,添加Session管理

我们需要维护一个线程安全的集合来保存所有活跃的客户端Session,客户端连接时把Session加入集合,断开时从集合移除,之后就能通过这些Session主动发起消息了。

package com.trice.server.web;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/WebSocketTestServlet")
public class WebSocketTestServlet {
    // 用线程安全的集合存储所有活跃客户端的Session,避免并发场景下的问题
    private static final Set<Session> CLIENT_SESSIONS = Collections.newSetFromMap(new ConcurrentHashMap<>());

    @OnOpen
    public void onOpen(Session session) {
        System.out.println("新连接建立... Session ID: " + session.getId());
        CLIENT_SESSIONS.add(session);
    }

    @OnClose
    public void onClose(Session session) {
        System.out.println("连接关闭... Session ID: " + session.getId());
        CLIENT_SESSIONS.remove(session);
    }

    @OnMessage
    public String onMessage(String message, Session session) {
        System.out.println("收到客户端[" + session.getId() + "]消息: " + message);
        String echoMsg = "服务器回声: " + message;
        return echoMsg;
    }

    @OnError
    public void onError(Session session, Throwable e) {
        System.err.println("客户端[" + session.getId() + "]出现错误");
        e.printStackTrace();
        // 出错时移除无效Session,避免资源浪费
        CLIENT_SESSIONS.remove(session);
    }

    // 向所有在线客户端广播消息的静态方法
    public static void broadcastMessage(String message) {
        for (Session session : CLIENT_SESSIONS) {
            if (session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(message);
                    System.out.println("已向客户端[" + session.getId() + "]发送消息: " + message);
                } catch (IOException e) {
                    System.err.println("向客户端[" + session.getId() + "]发送消息失败");
                    e.printStackTrace();
                }
            }
        }
    }

    // 向指定Session ID的客户端发送消息的静态方法
    public static void sendMessageToClient(String sessionId, String message) {
        for (Session session : CLIENT_SESSIONS) {
            if (session.getId().equals(sessionId) && session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(message);
                    System.out.println("已向客户端[" + sessionId + "]发送消息: " + message);
                } catch (IOException e) {
                    System.err.println("向客户端[" + sessionId + "]发送消息失败");
                    e.printStackTrace();
                }
                break;
            }
        }
    }
}

2. 触发服务端主动发消息的方式

你可以在任何业务逻辑里调用上面的静态方法来主动发消息,比如:

// 示例:在定时任务或业务事件中广播消息给所有客户端
WebSocketTestServlet.broadcastMessage("服务器广播:各位客户端好!");

// 示例:给特定Session ID的客户端单独发消息
WebSocketTestServlet.sendMessageToClient("abc-123-def", "服务器专属消息:你好呀!");

3. 客户端代码无需额外修改

你的客户端代码已经能完美处理服务端主动发来的消息——webSocket.onmessage会自动触发wsGetMessage方法,把消息显示在文本框里。要是想测试的话,启动服务后调用broadcastMessage,客户端马上就能收到消息。

4. 几个重要的注意点

  • 用ConcurrentHashMap实现的集合是线程安全的,能应对多客户端同时连接/断开的场景,避免并发问题。
  • 发送消息前一定要检查session.isOpen(),别给已经断开的连接发消息,不然会抛出异常。
  • 在@OnError和@OnClose里及时移除无效的Session,防止内存泄漏。

内容的提问来源于stack exchange,提问作者raksheetbhat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:17:41