| New file |
| | |
| | | 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<String, Session> 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()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |