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());
|
}
|
}
|
}
|
}
|
}
|