package com.ard.sample.component.websocket.service.impl; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; /** * WebSocket端点类:处理连接、消息收发、断开等事件 * 端点路径:ws://localhost:8080/ws/{username}(username为客户端标识) */ @ServerEndpoint("/ws/Dock/{username}") @Component public class WebSocketDockServer { // 静态变量:存储所有在线客户端的会话(线程安全) private static final ConcurrentHashMap ONLINE_USERS = new ConcurrentHashMap<>(); // 当前连接的用户名 private String username; /** * 客户端连接成功时触发 */ @OnOpen public void onOpen(Session session, @PathParam("username") String username) { this.username = username; // 保存会话 ONLINE_USERS.put(username, session); // 群发"用户上线"通知 sendToAll("系统通知:用户【" + username + "】已上线,当前在线人数:" + ONLINE_USERS.size()); System.out.println("用户【" + username + "】连接成功,在线人数:" + ONLINE_USERS.size()); } /** * 客户端断开连接时触发 */ @OnClose public void onClose() { // 移除会话 ONLINE_USERS.remove(username); // 群发"用户下线"通知 sendToAll("系统通知:用户【" + username + "】已下线,当前在线人数:" + ONLINE_USERS.size()); System.out.println("用户【" + username + "】断开连接,在线人数:" + ONLINE_USERS.size()); } /** * 收到客户端消息时触发 * 消息格式支持:"all:消息内容"(群发)、"username:消息内容"(指定用户发送) */ @OnMessage public void onMessage(String message) { System.out.println("收到【" + username + "】的消息:" + message); if (message.startsWith("all:")) { // 群发消息(格式:all:你好大家) String content = message.substring(4); sendToAll("【" + username + "】:" + content); } else if (message.contains(":")) { // 给指定用户发消息(格式:目标用户名:消息内容) String[] parts = message.split(":", 2); String targetUser = parts[0]; String content = parts[1]; sendToUser(targetUser, "【" + username + "】对你说:" + content); } else { // 默认群发 sendToAll("【" + username + "】:" + message); } } /** * 连接异常时触发 */ @OnError public void onError(Session session, Throwable error) { System.err.println("WebSocket错误(用户【" + username + "】):"); error.printStackTrace(); } // -------------------------- 消息发送工具方法 -------------------------- /** * 向单个用户发送消息 * @param targetUser 目标用户名 * @param message 消息内容 */ public static void sendToUser(String targetUser, String message) { Session session = ONLINE_USERS.get(targetUser); if (session != null && session.isOpen()) { // 检查会话是否有效 try { // 同步发送消息 session.getBasicRemote().sendText(message); } catch (IOException e) { System.err.println("向【" + targetUser + "】发送消息失败:" + e.getMessage()); } } else { System.out.println("用户【" + targetUser + "】不在线"); } } /** * 向所有在线用户群发消息 * @param message 消息内容 */ public static void sendToAll(String message) { for (Session session : ONLINE_USERS.values()) { if (session.isOpen()) { // 只给活跃会话发送 try { session.getBasicRemote().sendText(message); } catch (IOException e) { System.err.println("群发消息失败:" + e.getMessage()); } } } } }