package com.ruoyi.websocket.controller; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Controller; import com.alibaba.fastjson2.JSON; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.websocket.config.LoginUserPrincipal; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.Rooms; import com.ruoyi.system.service.IRoomsService; import com.ruoyi.websocket.dto.RoomMemberDTO; import com.ruoyi.websocket.service.RoomWebSocketService; /** * WebSocket 房间消息控制器 * * @author ruoyi */ @Controller public class RoomWebSocketController { @Autowired private SimpMessagingTemplate messagingTemplate; @Autowired private RoomWebSocketService roomWebSocketService; @Autowired private IRoomsService roomsService; private static final String TYPE_JOIN = "JOIN"; private static final String TYPE_LEAVE = "LEAVE"; private static final String TYPE_PING = "PING"; private static final String TYPE_MEMBER_JOINED = "MEMBER_JOINED"; private static final String TYPE_MEMBER_LEFT = "MEMBER_LEFT"; private static final String TYPE_MEMBER_LIST = "MEMBER_LIST"; private static final String TYPE_PONG = "PONG"; /** * 处理房间消息:JOIN、LEAVE、PING */ @MessageMapping("/room/{roomId}") public void handleRoomMessage(@DestinationVariable Long roomId, @Payload String payload, SimpMessageHeaderAccessor accessor) { LoginUser loginUser = null; if (accessor.getUser() instanceof LoginUserPrincipal) { loginUser = ((LoginUserPrincipal) accessor.getUser()).getLoginUser(); } if (loginUser == null) return; Map body = parsePayload(payload); if (body == null) return; String type = (String) body.get("type"); String sessionId = accessor.getSessionId(); if (sessionId == null) sessionId = UUID.randomUUID().toString(); if (TYPE_JOIN.equals(type)) { handleJoin(roomId, sessionId, loginUser, body); } else if (TYPE_LEAVE.equals(type)) { handleLeave(roomId, sessionId, loginUser); } else if (TYPE_PING.equals(type)) { handlePing(roomId, sessionId, loginUser); } } @SuppressWarnings("unchecked") private Map parsePayload(String payload) { try { return JSON.parseObject(payload, Map.class); } catch (Exception e) { return null; } } private void handleJoin(Long roomId, String sessionId, LoginUser loginUser, Map body) { Rooms room = roomsService.selectRoomsById(roomId); if (room == null) return; RoomMemberDTO member = buildMember(loginUser, sessionId, roomId, body); roomWebSocketService.joinRoom(roomId, sessionId, member); List members = roomWebSocketService.getRoomMembers(roomId); Map memberListMsg = new HashMap<>(); memberListMsg.put("type", TYPE_MEMBER_LIST); memberListMsg.put("members", members); Map joinedMsg = new HashMap<>(); joinedMsg.put("type", TYPE_MEMBER_JOINED); joinedMsg.put("member", member); String topic = "/topic/room/" + roomId; messagingTemplate.convertAndSend(topic, memberListMsg); } private void handleLeave(Long roomId, String sessionId, LoginUser loginUser) { RoomMemberDTO member = buildMember(loginUser, sessionId, roomId, null); roomWebSocketService.leaveRoom(roomId, sessionId, loginUser.getUserId()); Map msg = new HashMap<>(); msg.put("type", TYPE_MEMBER_LEFT); msg.put("member", member); msg.put("sessionId", sessionId); messagingTemplate.convertAndSend("/topic/room/" + roomId, msg); } private void handlePing(Long roomId, String sessionId, LoginUser loginUser) { roomWebSocketService.refreshSessionHeartbeat(sessionId); Map msg = new HashMap<>(); msg.put("type", TYPE_PONG); messagingTemplate.convertAndSendToUser(loginUser.getUsername(), "/queue/private", msg); } private RoomMemberDTO buildMember(LoginUser loginUser, String sessionId, Long roomId, Map body) { RoomMemberDTO dto = new RoomMemberDTO(); dto.setUserId(loginUser.getUserId()); dto.setUserName(loginUser.getUsername()); dto.setNickName(loginUser.getUser().getNickName()); dto.setAvatar(loginUser.getUser().getAvatar()); dto.setSessionId(sessionId); dto.setDeviceId(body != null && body.containsKey("deviceId") ? String.valueOf(body.get("deviceId")) : "default"); dto.setJoinedAt(System.currentTimeMillis()); Rooms room = roomsService.selectRoomsById(roomId); if (room != null && loginUser.getUserId().equals(room.getOwnerId())) { dto.setRole("owner"); } else if (StringUtils.isNotEmpty(loginUser.getUser().getUserLevel())) { dto.setRole(loginUser.getUser().getUserLevel()); } else { dto.setRole("member"); } return dto; } }