You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
5.6 KiB
147 lines
5.6 KiB
|
1 month ago
|
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<String, Object> 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<String, Object> 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<String, Object> body) {
|
||
|
|
Rooms room = roomsService.selectRoomsById(roomId);
|
||
|
|
if (room == null) return;
|
||
|
|
|
||
|
|
RoomMemberDTO member = buildMember(loginUser, sessionId, roomId, body);
|
||
|
|
roomWebSocketService.joinRoom(roomId, sessionId, member);
|
||
|
|
|
||
|
|
List<RoomMemberDTO> members = roomWebSocketService.getRoomMembers(roomId);
|
||
|
|
Map<String, Object> memberListMsg = new HashMap<>();
|
||
|
|
memberListMsg.put("type", TYPE_MEMBER_LIST);
|
||
|
|
memberListMsg.put("members", members);
|
||
|
|
|
||
|
|
Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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;
|
||
|
|
}
|
||
|
|
}
|