package com.hivekion.ws; import com.alibaba.fastjson2.JSON; import com.hivekion.Global; import com.hivekion.common.entity.RequestCmdInfo; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestParam; /** * [类的简要说明] *

* [详细描述,可选] *

* * @author LiDongYU * @since 2025/7/22 */ @ServerEndpoint("/ws/{scenarioId}/{room}") @Component @Slf4j public class WsServer { private static final ConcurrentHashMap lockMap = new ConcurrentHashMap<>(); // key -> 当前key下所有会话 private static final Map>> SESSION_MAP = new ConcurrentHashMap<>(); private static final Object lock = new Object(); private static final Object receiveLock = new Object(); @OnOpen public void onOpen(Session session, @PathParam("room") String room, @PathParam("scenarioId") String scenarioId) { log.info("onOpen::scenarioId: {}, room: {}", room, room); synchronized (lock) { if (SESSION_MAP.get(scenarioId) == null) { SESSION_MAP.put(scenarioId, new ConcurrentHashMap<>()); Map sessionMap = new ConcurrentHashMap<>(); sessionMap.put(session.getId(), session); SESSION_MAP.get(scenarioId).put(room, sessionMap); } else { if (SESSION_MAP.get(scenarioId).get(room) == null) { Map sessionMap = new ConcurrentHashMap<>(); sessionMap.put(session.getId(), session); SESSION_MAP.get(scenarioId).put(room, sessionMap); } else { SESSION_MAP.get(scenarioId).get(room).put(session.getId(), session); } } } } @OnClose public void onClose(Session session, @PathParam("room") String room, @PathParam("scenarioId") String scenarioId) { log.info("onClose::room: {}, scenarioId: {}", room, scenarioId); synchronized (lock) { //获取session信息 if (SESSION_MAP.get(scenarioId) != null) { if (SESSION_MAP.get(scenarioId).get(room) != null) { SESSION_MAP.get(scenarioId).get(room).remove(session.getId()); } } } } @OnMessage public void onMessage(String message, Session session, @PathParam("room") String room, @PathParam("scenarioId") Integer scenarioId) { synchronized (receiveLock) { try { log.info("onMessage::room: {}, message: {}", room, message); RequestCmdInfo requestCmdInfo = new RequestCmdInfo(); requestCmdInfo.setScenarioId((scenarioId)); requestCmdInfo.setRoom(room); requestCmdInfo.setCmdType(JSON.parseObject(message, RequestCmdInfo.class).getCmdType()); requestCmdInfo.setMessage(message); Global.receiveCmdInfoQueue.add(requestCmdInfo); } catch (Exception e) { log.error("onMessage::room: {}, message: {},error::", room, message, e); } } } @OnError public void onError(Session session, Throwable error, @PathParam("room") String room, @PathParam("scenarioId") String scenarioId) { log.info("onError::room: {},sessionId::{} error: ", room, session.getId(), error); onClose(session, room, scenarioId); } public static void sendMessage(Integer scenarioId, String message) { } public static void sendMessage(Integer scenarioId, String room, String message) { log.info("{},{}", scenarioId, room); synchronized (lock) { Map> roomMap = SESSION_MAP.get(String.valueOf(scenarioId)); // log.info("roomMap:{}", roomMap); if (roomMap != null) { if (roomMap.containsKey(room)) { Map singleRoomMap = roomMap.get(room); singleRoomMap.forEach((sessionId, session) -> { try { session.getBasicRemote().sendText(message); } catch (Exception e) { log.error("error::", e); } }); } } } } }