Skip to content

Commit

Permalink
Merge pull request #32 from Leets-Official/feat/#28/채팅-비지니스-로직-개선
Browse files Browse the repository at this point in the history
Feat/#28/채팅 비지니스 로직 개선
  • Loading branch information
koreaioi authored Nov 13, 2024
2 parents fab2a6f + 716607e commit a940dd2
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.leets.X.domain.chat.controller;

import com.leets.X.domain.chat.dto.request.ChatRoomCheckRequstDto;
import com.leets.X.domain.chat.dto.request.FindChatRoomRequestDto;
import com.leets.X.domain.chat.dto.response.ChatRoomResponseDto;
import com.leets.X.domain.chat.service.ChatRoomService;
import com.leets.X.global.common.response.ResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
Expand All @@ -13,6 +14,7 @@

import static com.leets.X.domain.chat.controller.ResponseMessage.*;

@Tag(name="ChatRoom")
@Slf4j
@RestController
@RequestMapping("/api/v1/chatRoom")
Expand All @@ -22,6 +24,7 @@ public class ChatRoomController {
private final ChatRoomService chatRoomService;

@PostMapping
@Operation(summary = "채팅 방 생성")
public ResponseDto<ChatRoomResponseDto> createChatRoom(@RequestBody @Valid FindChatRoomRequestDto findChatRoomRequestDto){
ChatRoomResponseDto response = chatRoomService.saveChatRoom(findChatRoomRequestDto);
return ResponseDto.response(CHATROOM_CREATE_SUCCESS.getCode(), CHATROOM_CREATE_SUCCESS.getMessage(), response);
Expand All @@ -31,13 +34,15 @@ public ResponseDto<ChatRoomResponseDto> createChatRoom(@RequestBody @Valid FindC

// user1Id와 user2Id의 채팅방이 있는 지 조회
@GetMapping("/{user1Id}/{user2Id}")
@Operation(summary = "채팅방 존재 여부 확인")
public ResponseDto<ChatRoomResponseDto> existChatRoom(@PathVariable Long user1Id, @PathVariable Long user2Id){
ChatRoomResponseDto response = chatRoomService.findUser1User2ChatRoom(user1Id , user2Id);

return ResponseDto.response(GET_ROOMID.getCode(), GET_ROOMID.getMessage(), response);
return ResponseDto.response(ROOMID_GET.getCode(), ROOMID_GET.getMessage(), response);
}

@PostMapping("/{roomId}") // addListener 테스트 용
@Operation(summary = "채팅 방 addListener 테스트")
public void addListener(@PathVariable @NotNull Long roomId) {
chatRoomService.addListener(roomId);
log.info(roomId+":addListener");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
package com.leets.X.domain.chat.controller;

import com.leets.X.domain.chat.dto.request.GetChatRoomRequestDto;
import com.leets.X.domain.chat.dto.response.ChattingDto;
import com.leets.X.domain.chat.dto.response.ChattingListResponseDto;
import com.leets.X.domain.chat.service.ChattingService;
import com.leets.X.global.common.response.ResponseDto;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

import static com.leets.X.domain.chat.controller.ResponseMessage.GET_CHATROOM;
import static com.leets.X.domain.chat.controller.ResponseMessage.GET_CHATTING_LIST;
import static com.leets.X.domain.chat.controller.ResponseMessage.CHATROOM_GET;
import static com.leets.X.domain.chat.controller.ResponseMessage.CHATTINGLIST_GET;

@Tag(name="Chatting(ChatMessage)")
@RestController
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class ChattingController {

private final ChattingService chattingService;

// 채팅방 하나를 조회해준다. (대화 내역을 돌려준다는 의미)
@GetMapping("/chatting/{roomId}/{page}/{size}")
public ResponseDto<ChattingDto> findChatting(@PathVariable Long roomId, @PathVariable Integer page, @PathVariable Integer size) {
ChattingDto response = chattingService.getChatRoom(roomId, page, size);
return ResponseDto.response(GET_CHATROOM.getCode(), GET_CHATROOM.getMessage(), response);
@Operation(summary = "하나의 채팅방 + 해당 채팅 내역 조회")
public ResponseDto<ChattingDto> findChatting(@PathVariable Long roomId, @PathVariable Integer page,
@PathVariable Integer size, @AuthenticationPrincipal String email) {
ChattingDto response = chattingService.getChatRoom(roomId, page, size, email);
return ResponseDto.response(CHATROOM_GET.getCode(), CHATROOM_GET.getMessage(), response);
}


@GetMapping("/chattingList/{userId}")
public ResponseDto<List<ChattingListResponseDto>> findChattingList(@PathVariable Long userId){
List<ChattingListResponseDto> response = chattingService.getChattingList(userId);
return ResponseDto.response(GET_CHATTING_LIST.getCode(), GET_CHATTING_LIST.getMessage(), response);
@Operation(summary = "유저가 속한 모든 채팅방 조회")
public ResponseDto<List<ChattingListResponseDto>> findChattingList(@PathVariable Long userId, @AuthenticationPrincipal String email){
List<ChattingListResponseDto> response = chattingService.getChattingList(userId, email);
return ResponseDto.response(CHATTINGLIST_GET.getCode(), CHATTINGLIST_GET.getMessage(), response);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
public enum ResponseMessage {

CHATROOM_CREATE_SUCCESS(201,"채팅방 생성에 성공했습니다."),
GET_CHATROOM(200, "하나의 채팅방을 반환합니다."),
GET_ROOMID(200, "채팅방 번호를 반환합니다."),
GET_CHATTING_LIST(200, "모든 채팅방 목록을 반환합니다.");
CHATROOM_GET(200, "하나의 채팅방을 반환합니다."),
ROOMID_GET(200, "채팅방 번호를 반환합니다."),
CHATTINGLIST_GET(200, "모든 채팅방 목록을 반환합니다.");

private final int code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
package com.leets.X.domain.chat.dto.response;

import com.leets.X.domain.user.domain.User;

import java.util.List;

public record ChattingDto(
Long user1Id,
Long user2Id,
String user1Name,
String user2Name,
Long senderId,
String senderName,

Long opponentId,
String opponentImageUrl,
String opponentName,

List<ChatMessageResponseDto> chatMessageList
) {

public static ChattingDto of(User sender, User opponent, List<ChatMessageResponseDto> chatMessageList) {
return new ChattingDto(
sender.getId(), sender.getName(),
opponent.getId(), opponent.getName(), opponent.getImage().getUrl(),
chatMessageList
);
}

}
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
package com.leets.X.domain.chat.dto.response;

import com.leets.X.domain.chat.entity.ChatRoom;
import com.leets.X.domain.user.domain.User;

public record ChattingListResponseDto(
Long roomId,
Long user1Id,
Long user2Id,
String user1Name,
String user2Name,

Long senderId,
String senderName,

Long opponentId,
String opponentImageUrl,
String opponentName,

LatestMessageDto latestMessageDto
) {
public static ChattingListResponseDto of(ChatRoom chatRoom, LatestMessageDto latestMessageDto) {
public static ChattingListResponseDto of(Long roomId, User sender, User opponent, LatestMessageDto latestMessageDto) {
return new ChattingListResponseDto(
chatRoom.getId(),
chatRoom.getUser1().getId(),
chatRoom.getUser2().getId(),
chatRoom.getUser1().getCustomId(),
chatRoom.getUser2().getCustomId(),
roomId,
sender.getId(), sender.getName(),
opponent.getId(), opponent.getName(), opponent.getImage().getUrl(),
latestMessageDto
);
}
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/com/leets/X/domain/chat/entity/ChatRoom.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@ public class ChatRoom extends BaseTimeEntity {
@JoinColumn(name = "user2_id")
private User user2;

private String lastMessage;

public static ChatRoom of(User user1, User user2) {

return ChatRoom.builder()
.user1(user1)
.user2(user2)
.lastMessage("")
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.leets.X.domain.chat.exception;

import com.leets.X.global.common.exception.BaseException;

import static com.leets.X.domain.chat.exception.ErrorMessage.CHATROOM_EXIST;

public class ChatRoomExistException extends BaseException {
public ChatRoomExistException() {
super(CHATROOM_EXIST.getCode(),CHATROOM_EXIST.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
@AllArgsConstructor
public enum ErrorMessage {

NOT_FOUND_CHATROOM(400, "해당 채팅방을 찾을 수 없습니다.");
CHATROOM_NOT_FOUND(400, "해당 채팅방을 찾을 수 없습니다."),
CHATROOM_EXIST(400, "해당 채팅방이 이미 존재합니다");

private final int code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.leets.X.domain.chat.exception;

import com.leets.X.global.common.exception.BaseException;
import static com.leets.X.domain.chat.exception.ErrorMessage.NOT_FOUND_CHATROOM;
import static com.leets.X.domain.chat.exception.ErrorMessage.CHATROOM_NOT_FOUND;

public class NotFoundChatRoomException extends BaseException {
public NotFoundChatRoomException() {
super(NOT_FOUND_CHATROOM.getCode(), NOT_FOUND_CHATROOM.getMessage());
super(CHATROOM_NOT_FOUND.getCode(), CHATROOM_NOT_FOUND.getMessage());
}
}
21 changes: 16 additions & 5 deletions src/main/java/com/leets/X/domain/chat/service/ChatRoomService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.leets.X.domain.chat.dto.request.FindChatRoomRequestDto;
import com.leets.X.domain.chat.dto.response.*;
import com.leets.X.domain.chat.entity.ChatRoom;
import com.leets.X.domain.chat.exception.ChatRoomExistException;
import com.leets.X.domain.chat.exception.NotFoundChatRoomException;
import com.leets.X.domain.chat.redis.RedisListener;
import com.leets.X.domain.chat.repository.ChatRoomRepository;
Expand All @@ -29,22 +30,32 @@ public ChatRoomResponseDto saveChatRoom(FindChatRoomRequestDto findChatRoomReque
User user1 = userService.find(findChatRoomRequestDto.user1Id());
User user2 = userService.find(findChatRoomRequestDto.user2Id());

checkChatRoom(user1.getId(), user2.getId());
ChatRoom savedRoom = chatRoomRepository.save(ChatRoom.of(user1, user2)); // 채팅방 RDB에 저장

redisMessageListener.adaptMessageListener(savedRoom.getId()); // 리스너 등록
return new ChatRoomResponseDto(savedRoom.getId());
}



public ChatRoomResponseDto findUser1User2ChatRoom(Long user1Id , Long user2Id) {
Long result = chatRoomRepository.findRoomIdByUserIds(user1Id , user2Id)
.orElseThrow(NotFoundChatRoomException::new);
return new ChatRoomResponseDto(result);
return new ChatRoomResponseDto(findUsersChatRoom(user1Id, user2Id));
}

// 테스트를 위해서 만들어둠. 추후 삭제
public void addListener(Long roomId) {
redisMessageListener.adaptMessageListener(roomId); // 리스너 등록
}



private void checkChatRoom(Long user1Id, Long user2Id) {
chatRoomRepository.findRoomIdByUserIds(user1Id, user2Id).ifPresent(c->{
throw new ChatRoomExistException();
});
}

private Long findUsersChatRoom(Long user1Id, Long user2Id) {
return chatRoomRepository.findRoomIdByUserIds(user1Id, user2Id)
.orElseThrow(NotFoundChatRoomException::new);
}
}
35 changes: 28 additions & 7 deletions src/main/java/com/leets/X/domain/chat/service/ChattingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.leets.X.domain.chat.repository.ChatMessageRepository;
import com.leets.X.domain.chat.repository.ChatRoomRepository;
import com.leets.X.domain.user.domain.User;
import com.leets.X.domain.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
Expand All @@ -26,31 +27,36 @@ public class ChattingService {
private final ChatRoomRepository chatRoomRepository;
private final ChatMessageRepository chatMessageRepository;
private final RedisListener redisMessageListener;
private final UserService userService;

public ChattingDto getChatRoom(Long roomId, Integer page, Integer size) {
public ChattingDto getChatRoom(Long roomId, Integer page, Integer size, String email) {
ChatRoom findRoom = validateChatRoom(roomId);
User user1 = findRoom.getUser1();
User user2 = findRoom.getUser2();
redisMessageListener.adaptMessageListener(findRoom.getId()); // 채팅방 내역 조회시 리스너 등록 추가 (운영 시 삭제)

List<ChatMessageResponseDto> chatMessageList = generateChatRoomMessages(roomId, page, size);
return new ChattingDto(user1.getId(), user2.getId(), user1.getCustomId(), user2.getCustomId(), chatMessageList);
}
User sender = userService.find(email);

return findOpponent(sender, findRoom.getUser1(), findRoom.getUser2(), chatMessageList);
}

public List<ChattingListResponseDto> getChattingList(Long userId) { // 추후 JWT 파싱으로 받아내기.
public List<ChattingListResponseDto> getChattingList(Long userId, String email) { // 추후 JWT 파싱으로 받아내기.
List<ChatRoom> chatRooms = validateChatRommList(userId);

return chatRooms.stream()
.map(chatRoom -> {
ChatMessage latestMessage = chatMessageRepository.findTopByRoomIdOrderByCreatedAtDesc(chatRoom.getId()).orElse(null);
LatestMessageDto latestMessageDto = (latestMessage != null)
? LatestMessageDto.of(latestMessage) : new LatestMessageDto("", null);
return ChattingListResponseDto.of(chatRoom, latestMessageDto);
User sender = userService.find(email);
return findOpponentToAllChat(chatRoom, sender,chatRoom.getUser1(), chatRoom.getUser2(), latestMessageDto);
})
.collect(Collectors.toList());
}

/*
* 리팩토링
* */

private List<ChatMessageResponseDto> generateChatRoomMessages(Long roomId, Integer page, Integer size) {
return chatMessageRepository.findByRoomIdOrderByCreatedAtDesc(
roomId, PageRequest.of(page- 1, size))
Expand All @@ -60,6 +66,21 @@ private List<ChatMessageResponseDto> generateChatRoomMessages(Long roomId, Integ
.collect(Collectors.toList());
}

private static ChattingDto findOpponent(User sender, User user1, User user2, List<ChatMessageResponseDto> chatMessageList) {
if(sender.equals(user1)) { // user1 이 본인
return ChattingDto.of(user1, user2, chatMessageList);
}else{
return ChattingDto.of(user2, user1, chatMessageList);
}
}

private static ChattingListResponseDto findOpponentToAllChat(ChatRoom chatRoom, User sender,User user1, User user2, LatestMessageDto latestMessageDto) {
if(sender.equals(user1)) { // user1 이 본인
return ChattingListResponseDto.of(chatRoom.getId(), user1, user2, latestMessageDto);
}else{
return ChattingListResponseDto.of(chatRoom.getId(), user2, user1, latestMessageDto);
}
}

private ChatRoom validateChatRoom(Long roomId) {
return chatRoomRepository.findById(roomId)
Expand Down

0 comments on commit a940dd2

Please sign in to comment.