/**
* 방 입장
*/
@PreAuthorize("isAuthenticated()")
@GetMapping("/rooms/{roomId}")
public String showRoom(@PathVariable Long roomId, Model model, @AuthenticationPrincipal SecurityUser user) {
// 1,
ChatRoom chatRoom = chatRoomService.findById(roomId);
Matching matching = chatRoom.getMatching();
// 2,
RsData rsData = chatRoomService`canAddChatRoomUser`(ch 로직, user.getId(), matching); 채팅방에 유저가 들어갈 수 있는지 확인해주는 로직
if (rsData.isFail()) {
return rq.historyBack(rsData);
}
// 3,
ChatRoomDto chatRoomDto = chatRoomService.getByIdAndUserId(roomId, user.getId());
// 4,
if (chatRoomDto.getType().equals(ROOMIN) || chatRoomDto.getType().equals(EXIT)){
// 사용자가 방에 입장할 때 메시지 생성
String enterMessage = " < " + user.getUsername() + "님이 입장하셨습니다. >";
chatMessageService.createAndSave(enterMessage, user.getId(), roomId, ENTER);
// 실시간으로 입장 메시지 전송
SignalResponse signalResponse = SignalResponse.builder()
.type(NEW_MESSAGE)
.message(enterMessage) // 입장 메시지 설정
.build();
template.convertAndSend("/topic/chats/" + chatRoom.getId(), signalResponse);
}
// 5,
chatRoomService.updateChatUserType(roomId, user.getId());
// 6,
chatRoomService.changeParticipant(chatRoom);
model.addAttribute("chatRoom", chatRoomDto);
model.addAttribute("user", user);
return "chat/room";
}
4, 채팅방에 들어갔을 경우 입장메시지를 띄워주는 역활을 합니다. 유저가 처음들어갔을 경우에는 ROOMIN
, 유저가 나갔다가 다시 들어갈 경우는 EXIT
으로 convertAndSend("/topic/chats/" + chatRoom.getId()
구독을 통하여 메시지를 던져줍니다.
1, findById(roomId)
채팅방이 존재하는지 찾기 위한 로직
public ChatRoom findById(Long roomId) {
return chatRoomRepository.findById(roomId)
.orElseThrow(() -> new NoChatRoomException("방이 존재하지 않습니다."));
}
2, canAddChatRoomUser
채팅방에 유저가 들어갈 수 있는지 확인해주는 로직
public RsData canAddChatRoomUser(ChatRoom chatRoom, Long userId, Matching matching) {
// 발견한 건가?..발견한 것 같아!!!!
if(!getChatUser(chatRoom, userId).isEmpty() && !matching.canAddParticipant()) {
boolean whatIsTrueFalse = isExitUser(chatRoom, userId);
log.info("whatIsTrueFalse = {}", whatIsTrueFalse);
if(whatIsTrueFalse) {
return RsData.of("F-2", "모임 정원 초과!");
}
}
// 이미 채팅방에 동일 유저가 존재하는 경우
if (!getChatUser(chatRoom, userId).isEmpty()) {
ChatUser chatUser = getChatUser(chatRoom, userId).get();
return checkChatUserType(chatUser);
}
if (!matching.canAddParticipant()) {
return RsData.of("F-2", "모임 정원 초과!"); // 참여자 수가 capacity 보다 많으면 참가 하지 못하도록
}
return RsData.of("S-1", "새로운 모임 채팅방에 참여합니다.");
}
3, getByIdAndUserId
실질적으로 방에 들어가는 로직입니다. 유저가 방에 들어갈 수 있는 상태인지 Service 부분에서 한번 더 체크합니다.
@Transactional
public ChatRoomDto getByIdAndUserId(Long roomId, long userId) {
User user = userService.findByIdElseThrow(userId);
ChatRoom chatRoom = findById(roomId);
/**
* 매칭 파트너가 아닌데 채팅방에 들어가려고 하면 IllegalArgumentException 던저주기
*/
Matching matching = chatRoom.getMatching();
matching.getMatchingPartners().stream()
.filter(matchingPartner -> matchingPartner.getUser().getId().equals(user.getId()))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("너 매칭 파트너 아니야"));
addChatRoomUser(chatRoom, user, userId);
chatRoom.getChatUsers().stream()
.filter(chatUser -> chatUser.getUser().getId().equals(userId))
.findFirst()
.orElseThrow();
return ChatRoomDto.fromChatRoom(chatRoom, user);
}
5, 방에 들어간 유저를 COMMON
타입으로 바까주는 로직입니다. COMMON으로 바뀐 유저는 현재 채팅방에 들어가있는 상태의 유저입니다.
@Transactional
public void updateChatUserType(Long roomId, Long userId) {
ChatRoom chatRoom = chatUserService.findByRoomId(roomId);
User user = userService.findByIdElseThrow(userId);
UserTypeChange(chatRoom, user);
}
/**
* COMMON으로 Type 수정
*/
public void UserTypeChange(ChatRoom chatRoom, User user) {
ChatUser chatUser = chatUserService.findByChatRoomAndUser(chatRoom, user);
chatUser.changeUserCommonType();
}
6, 저희 서비스는 매칭에 인원 제한이 있기에 들어간 유저의 카운터를 증가시켜주는 로직입니다.
@Transactional
public void changeParticipant(ChatRoom chatRoom) {
Long commonParticipantsCount = getCommonParticipantsCount(chatRoom);
log.info("commonParticipantsCount = {} ", commonParticipantsCount);
chatRoom.getMatching().updateParticipant(commonParticipantsCount);
}