[Sprinboot] WebSocket, STOMP 활용한 채팅 기능 - 2 (채팅방 입장)

bw1611·2023년 7월 7일
0

WebSocket

목록 보기
3/3

채팅방 입장

  • ChatRoomController
    /**
     * 방 입장
     */
    @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() 구독을 통하여 메시지를 던져줍니다.

  • ChatRoomService

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);
    }
profile
Java BackEnd Developer

0개의 댓글

Powered by GraphCDN, the GraphQL CDN