From 0178094488bf30aab55d0d6caad8b2fd1fc1f512 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:18:49 +0900 Subject: [PATCH 01/28] =?UTF-8?q?refactor:=20#17=20=EB=94=94=EB=A0=89?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 디렉토리 컨벤션에 맞게 디렉토리 위치를 수정합니다. --- .../exception/ChatRoomNotFoundException.java | 4 ++-- .../domain/exception/ChatRoomForbiddenException.java | 11 ----------- 2 files changed, 2 insertions(+), 13 deletions(-) rename src/main/java/com/leets/xcellentbe/domain/{chatroom/domain => chatRoom}/exception/ChatRoomNotFoundException.java (81%) delete mode 100644 src/main/java/com/leets/xcellentbe/domain/chatroom/domain/exception/ChatRoomForbiddenException.java diff --git a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/exception/ChatRoomNotFoundException.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/exception/ChatRoomNotFoundException.java similarity index 81% rename from src/main/java/com/leets/xcellentbe/domain/chatroom/domain/exception/ChatRoomNotFoundException.java rename to src/main/java/com/leets/xcellentbe/domain/chatRoom/exception/ChatRoomNotFoundException.java index 105f827..71ad22a 100644 --- a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/exception/ChatRoomNotFoundException.java +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/exception/ChatRoomNotFoundException.java @@ -1,11 +1,11 @@ -package com.leets.xcellentbe.domain.chatroom.domain.exception; +package com.leets.xcellentbe.domain.chatRoom.exception; import com.leets.xcellentbe.global.error.ErrorCode; import com.leets.xcellentbe.global.error.exception.CommonException; public class ChatRoomNotFoundException extends CommonException { - public ChatRoomNotFoundException() { + public ChatRoomNotFoundException() { super(ErrorCode.CHAT_ROOM_NOT_FOUND); } } diff --git a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/exception/ChatRoomForbiddenException.java b/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/exception/ChatRoomForbiddenException.java deleted file mode 100644 index 507176f..0000000 --- a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/exception/ChatRoomForbiddenException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.leets.xcellentbe.domain.chatroom.domain.exception; - -import com.leets.xcellentbe.global.error.ErrorCode; -import com.leets.xcellentbe.global.error.exception.CommonException; - -public class ChatRoomForbiddenException extends CommonException { - public ChatRoomForbiddenException() { - - super(ErrorCode.CHAT_ROOM_FORBIDDEN); - } -} From 940f03cafd8052cff016910cd5e3df403e3573ce Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:20:09 +0900 Subject: [PATCH 02/28] =?UTF-8?q?feat:=20#17=20WebSocket=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=95=20=EA=B5=AC=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - STOMP 엔드포인트("/ws") 등록 - 간단한 메시지 브로커("/sub") 활성화 - 애플리케이션 목적지 접두사("/pub") 설정 --- .../global/config/WebSocketConfig.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/global/config/WebSocketConfig.java diff --git a/src/main/java/com/leets/xcellentbe/global/config/WebSocketConfig.java b/src/main/java/com/leets/xcellentbe/global/config/WebSocketConfig.java new file mode 100644 index 0000000..71ee8da --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/global/config/WebSocketConfig.java @@ -0,0 +1,23 @@ +package com.leets.xcellentbe.global.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + config.enableSimpleBroker("/sub"); + config.setApplicationDestinationPrefixes("/pub"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); + } +} From db4605a16902a6112f0bc9c357d96b0243c884c2 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:22:05 +0900 Subject: [PATCH 03/28] =?UTF-8?q?feat:=20#17=20Redis=20=EA=B5=AC=EC=84=B1?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RedisMessageListenerContainer 빈 등록 - RedisTemplate 빈 등록 (기본 값, DMDto 전용) - Redis 키/값 직렬화기 설정 (StringRedisSerializer, Jackson2JsonRedisSerializer) --- .../global/config/redis/RedisConfig.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/global/config/redis/RedisConfig.java diff --git a/src/main/java/com/leets/xcellentbe/global/config/redis/RedisConfig.java b/src/main/java/com/leets/xcellentbe/global/config/redis/RedisConfig.java new file mode 100644 index 0000000..d2698cc --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/global/config/redis/RedisConfig.java @@ -0,0 +1,40 @@ +package com.leets.xcellentbe.global.config.redis; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import com.leets.xcellentbe.domain.dm.dto.DMDto; + +@Configuration +public class RedisConfig { + + @Bean + public RedisMessageListenerContainer redisMessageListener(RedisConnectionFactory connectionFactory) { + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + return container; + } + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(connectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class)); + return redisTemplate; + } + + @Bean + public RedisTemplate redisTemplateMessage(RedisConnectionFactory connectionFactory) { + RedisTemplate redisTemplateMessage = new RedisTemplate<>(); + redisTemplateMessage.setConnectionFactory(connectionFactory); + redisTemplateMessage.setKeySerializer(new StringRedisSerializer()); + redisTemplateMessage.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class)); + return redisTemplateMessage; + } +} From 40cbae46d4cab85ef8ededf10708145932ea5c3e Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:23:07 +0900 Subject: [PATCH 04/28] =?UTF-8?q?feat:=20#17=20Redis=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=ED=8D=BC=EB=B8=94=EB=A6=AC=EC=85=94=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DMDto를 사용하여 주어진 채널 토픽에 메시지 발행 기능 구현 --- .../global/redis/RedisPublisher.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/global/redis/RedisPublisher.java diff --git a/src/main/java/com/leets/xcellentbe/global/redis/RedisPublisher.java b/src/main/java/com/leets/xcellentbe/global/redis/RedisPublisher.java new file mode 100644 index 0000000..5530e7f --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/global/redis/RedisPublisher.java @@ -0,0 +1,19 @@ +package com.leets.xcellentbe.global.redis; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.stereotype.Service; + +import com.leets.xcellentbe.domain.dm.dto.DMDto; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class RedisPublisher { + private final RedisTemplate redisTemplate; + + public void publish(ChannelTopic topic, DMDto dmDto) { + redisTemplate.convertAndSend(topic.getTopic(), dmDto); + } +} From 6aea3e8f1a557d60b046bdf5c478a9759e791db0 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:23:31 +0900 Subject: [PATCH 05/28] =?UTF-8?q?feat:=20#17=20Redis=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=8B=A0=EA=B8=B0=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Redis에서 수신한 메시지를 처리하여 DMDto로 변환 후 해당 채팅방에 발행하는 기능 구현 --- .../global/redis/RedisSubscriber.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/global/redis/RedisSubscriber.java diff --git a/src/main/java/com/leets/xcellentbe/global/redis/RedisSubscriber.java b/src/main/java/com/leets/xcellentbe/global/redis/RedisSubscriber.java new file mode 100644 index 0000000..d12df30 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/global/redis/RedisSubscriber.java @@ -0,0 +1,35 @@ +package com.leets.xcellentbe.global.redis; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.leets.xcellentbe.domain.dm.dto.DMDto; + +import lombok.RequiredArgsConstructor; + +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.messaging.simp.SimpMessageSendingOperations; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class RedisSubscriber implements MessageListener { + private final ObjectMapper objectMapper; + private final RedisTemplate redisTemplate; + private final SimpMessageSendingOperations simpMessageSendingOperations; + + @Override + public void onMessage(Message message, byte[] pattern) { + try { + String publishMessage = redisTemplate.getStringSerializer().deserialize(message.getBody()); + DMDto dmDto = objectMapper.readValue(publishMessage, DMDto.class); + simpMessageSendingOperations.convertAndSend("/sub/chat/" + dmDto.chatRoomId(), dmDto); + } catch (JsonMappingException e) { + throw new RuntimeException(); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } +} From c7316c661d802377c398511fa895cd768f5ee92f Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:25:14 +0900 Subject: [PATCH 06/28] =?UTF-8?q?chore:=20#17=20WebSocket=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Spring Boot WebSocket 스타터 의존성 추가 --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index dffee5b..a8a4199 100644 --- a/build.gradle +++ b/build.gradle @@ -74,6 +74,8 @@ dependencies { implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0' + // Websocket + implementation 'org.springframework.boot:spring-boot-starter-websocket' } tasks.named('test') { From 311ee899eb05975ad67d454c63e481788590b453 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:25:56 +0900 Subject: [PATCH 07/28] =?UTF-8?q?feat:=20#17=20ChatRoom=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Chatroom 클래스를 ChatRoom 클래스로 리팩토링 - 사용자(sender, receiver) 간의 관계 추가 - 마지막 메시지 및 삭제 상태 열 추가 - 빌더 패턴을 통한 객체 생성 메서드 추가 - 수신자 업데이트 및 마지막 메시지 업데이트 메서드 추가 - 삭제 상태 변경 메서드 추가 --- .../domain/chatRoom/domain/ChatRoom.java | 76 +++++++++++++++++++ .../domain/chatroom/domain/Chatroom.java | 30 -------- 2 files changed, 76 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/ChatRoom.java delete mode 100644 src/main/java/com/leets/xcellentbe/domain/chatroom/domain/Chatroom.java diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/ChatRoom.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/ChatRoom.java new file mode 100644 index 0000000..7fb89f8 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/ChatRoom.java @@ -0,0 +1,76 @@ +package com.leets.xcellentbe.domain.chatRoom.domain; + +import java.util.UUID; + +import com.leets.xcellentbe.domain.shared.BaseTimeEntity; +import com.leets.xcellentbe.domain.shared.DeletedStatus; +import com.leets.xcellentbe.domain.user.domain.User; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ChatRoom extends BaseTimeEntity { + + @Id + @Column(name = "chatRoom_id") + @GeneratedValue(strategy = GenerationType.UUID) + private UUID chatRoomId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "sender_id") + private User sender; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "receiver_id") + private User receiver; + + @Column + private String lastMessage; + + @NotNull + @Column + @Enumerated(EnumType.STRING) + private DeletedStatus deletedStatus; + + public static ChatRoom create(User sender, User receiver) { + return ChatRoom.builder() + .sender(sender) + .receiver(receiver) + .build(); + } + + @Builder + private ChatRoom(User sender, User receiver) { + this.sender = sender; + this.receiver = receiver; + this.deletedStatus = DeletedStatus.NOT_DELETED; + } + + public void updateReceiver(User receiver) { + this.receiver = receiver; + } + + public void updateLastMessage(String lastMessage) { + this.lastMessage = lastMessage; + } + + public void delete() { + this.deletedStatus = DeletedStatus.DELETED; + } +} diff --git a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/Chatroom.java b/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/Chatroom.java deleted file mode 100644 index 2e901d0..0000000 --- a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/Chatroom.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.leets.xcellentbe.domain.chatroom.domain; - -import java.util.UUID; - -import com.leets.xcellentbe.domain.shared.BaseTimeEntity; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Chatroom extends BaseTimeEntity { - - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID ChatroomId; - - @Column(length = 50) - private String lastParticipantName; - - @Column - private String lastMessage; -} From 24902e126c43f331d23c28cc97da2cc45b7df7c9 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:29:45 +0900 Subject: [PATCH 08/28] =?UTF-8?q?feat:=20#17=20ChatRoomDto=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EB=B3=80=ED=99=98=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatRoomDto 레코드 추가 - DMRequest와 User를 이용한 ChatRoomDto 생성 메서드 추가 - UUID, senderId, receiverId 필드를 포함한 ChatRoomDto 정의 --- .../domain/chatRoom/dto/ChatRoomDto.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/chatRoom/dto/ChatRoomDto.java diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/dto/ChatRoomDto.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/dto/ChatRoomDto.java new file mode 100644 index 0000000..8128280 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/dto/ChatRoomDto.java @@ -0,0 +1,24 @@ +package com.leets.xcellentbe.domain.chatRoom.dto; + +import java.io.Serial; +import java.io.Serializable; +import java.util.UUID; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.leets.xcellentbe.domain.dm.dto.request.DMRequest; +import com.leets.xcellentbe.domain.user.domain.User; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ChatRoomDto(UUID chatRoomId, Long senderId, Long receiverId) implements Serializable { + + @Serial + private static final long serialVersionUID = 6494678977089006639L; + + public static ChatRoomDto of(DMRequest dmRequest, User user) { + return new ChatRoomDto(null, user.getUserId(), dmRequest.receiverId()); + } + + public static ChatRoomDto of(UUID chatRoomId, User sender, User receiver) { + return new ChatRoomDto(chatRoomId, sender.getUserId(), receiver.getUserId()); + } +} From 88888006460baba35a5edd6c6ac01e6e0ec1c9c4 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:30:27 +0900 Subject: [PATCH 09/28] =?UTF-8?q?feat:=20#17=20ChatRoomRepository=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatRoomRepository 인터페이스 확장 - sender와 receiver에 따라 삭제되지 않은 채팅방 목록을 조회하는 메서드 추가 - 특정 sender와 receiver를 가진 채팅방을 삭제 상태에 따라 조회하는 메서드 추가 - 채팅방 ID와 삭제 상태를 기준으로 채팅방을 조회하는 메서드 추가 --- .../domain/repository/ChatRoomRepository.java | 23 +++++++++++++++++++ .../domain/repository/ChatroomRepository.java | 10 -------- 2 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/repository/ChatRoomRepository.java delete mode 100644 src/main/java/com/leets/xcellentbe/domain/chatroom/domain/repository/ChatroomRepository.java diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/repository/ChatRoomRepository.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/repository/ChatRoomRepository.java new file mode 100644 index 0000000..3090f3c --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/domain/repository/ChatRoomRepository.java @@ -0,0 +1,23 @@ +package com.leets.xcellentbe.domain.chatRoom.domain.repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; +import com.leets.xcellentbe.domain.shared.DeletedStatus; +import com.leets.xcellentbe.domain.user.domain.User; + +public interface ChatRoomRepository extends JpaRepository { + + List findBySenderOrReceiverAndDeletedStatusNot(User sender, User receiver, DeletedStatus deletedStatus); + + Optional findByChatRoomIdAndSenderOrChatRoomIdAndReceiverAndDeletedStatusNot(UUID ChatRoomId, User sender, + UUID ChatRoomId1, User receiver, DeletedStatus deletedStatus); + + ChatRoom findBySenderAndReceiverAndDeletedStatusNot(User sender, User receiver, DeletedStatus deletedStatus); + + Optional findByChatRoomIdAndDeletedStatusNot(UUID charRoomId, DeletedStatus deletedStatus); +} diff --git a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/repository/ChatroomRepository.java b/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/repository/ChatroomRepository.java deleted file mode 100644 index 02e4180..0000000 --- a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/repository/ChatroomRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.leets.xcellentbe.domain.chatroom.domain.repository; - -import java.util.UUID; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.leets.xcellentbe.domain.chatroom.domain.Chatroom; - -public interface ChatroomRepository extends JpaRepository { -} From d56240dba1133b45f00180ebc15f78124de9ab4b Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:31:00 +0900 Subject: [PATCH 10/28] =?UTF-8?q?feat:=20#17=20ChatRoomService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20Redis=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatRoomService 클래스 구현 - DMRequest를 기반으로 대화방 생성 메서드 추가 - 사용자별 대화방 목록 조회 메서드 추가 - 대화방 ID로 대화방 찾기 메서드 추가 - 대화방 삭제 메서드 구현 - Redis를 사용하여 메시지 저장 및 채널 토픽 관리 - 사용자 입장 시 대화방 채널 생성 및 관리 기능 추가 --- .../chatRoom/service/ChatRoomService.java | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java new file mode 100644 index 0000000..1bd8ab2 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java @@ -0,0 +1,146 @@ +package com.leets.xcellentbe.domain.chatRoom.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.stereotype.Service; + +import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; +import com.leets.xcellentbe.domain.chatRoom.domain.repository.ChatRoomRepository; +import com.leets.xcellentbe.domain.chatRoom.dto.ChatRoomDto; +import com.leets.xcellentbe.domain.chatRoom.exception.ChatRoomNotFoundException; +import com.leets.xcellentbe.domain.dm.domain.DM; +import com.leets.xcellentbe.domain.dm.domain.repository.DMRepository; +import com.leets.xcellentbe.domain.dm.dto.request.DMRequest; +import com.leets.xcellentbe.domain.dm.dto.response.DMResponse; +import com.leets.xcellentbe.domain.shared.DeletedStatus; +import com.leets.xcellentbe.domain.user.domain.User; +import com.leets.xcellentbe.domain.user.domain.repository.UserRepository; +import com.leets.xcellentbe.domain.user.exception.UserNotFoundException; +import com.leets.xcellentbe.global.redis.RedisSubscriber; + +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ChatRoomService { + + private final ChatRoomRepository chatRoomRepository; + private final DMRepository dmRepository; + private final UserRepository userRepository; + private final RedisMessageListenerContainer redisMessageListener; + private final RedisSubscriber redisSubscriber; + + private static final String Message_Rooms = "MESSAGE_ROOM"; + private final RedisTemplate redisTemplate; + private HashOperations opsHashMessageRoom; + + private Map topics; + + @PostConstruct + private void init() { + opsHashMessageRoom = redisTemplate.opsForHash(); + topics = new HashMap<>(); + } + + public DMResponse createChatRoom(DMRequest dmRequest, User user) { + User receiver = userRepository.findById(dmRequest.receiverId()).orElseThrow(UserNotFoundException::new); + + ChatRoom chatRoom = chatRoomRepository.findBySenderAndReceiverAndDeletedStatusNot(user, receiver, DeletedStatus.DELETED); + + if ((chatRoom == null) || (chatRoom != null && (!user.equals(chatRoom.getSender()) && !receiver.equals( + chatRoom.getReceiver())))) { + ChatRoomDto chatRoomDto = ChatRoomDto.of(dmRequest, user); + opsHashMessageRoom.put(Message_Rooms, user.getUserName(), chatRoomDto); + + chatRoom = chatRoomRepository.save(ChatRoom.create(user, receiver)); + + return new DMResponse(chatRoom); + } else { + return new DMResponse(chatRoom.getChatRoomId()); + } + } + + public List findAllChatRoomByUser(User user) { + List chatRooms = chatRoomRepository.findBySenderOrReceiverAndDeletedStatusNot(user, user, DeletedStatus.DELETED); + + List dmRespons = new ArrayList<>(); + + for (ChatRoom chatRoom : chatRooms) { + DMResponse messageRoomDto; + DM latestMessage; + + if (user.equals(chatRoom.getSender())) { + messageRoomDto = new DMResponse( + chatRoom.getChatRoomId(), + chatRoom.getSender(), + chatRoom.getReceiver()); + } else { + messageRoomDto = new DMResponse( + chatRoom.getChatRoomId(), + chatRoom.getSender(), + chatRoom.getReceiver()); + } + + latestMessage = dmRepository.findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(chatRoom, DeletedStatus.DELETED); + + if (latestMessage != null) { + messageRoomDto.updateLatestMessageCreatedAt(latestMessage.getCreatedAt()); + messageRoomDto.updateLatestMessageContent(latestMessage.getMessage()); + } + + dmRespons.add(messageRoomDto); + } + + return dmRespons; + } + + public ChatRoomDto findChatRoom(UUID chatRoomId, User user) { + ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndDeletedStatusNot(chatRoomId, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); + + User receiver = chatRoom.getReceiver(); + + chatRoom = chatRoomRepository.findByChatRoomIdAndSenderOrChatRoomIdAndReceiverAndDeletedStatusNot(chatRoomId, user, + chatRoomId, receiver, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); + + return ChatRoomDto.of(chatRoom.getChatRoomId(), chatRoom.getSender(), chatRoom.getReceiver()); + } + + public String deleteChatRoom(UUID chatRoomId, User user) { + ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndSenderOrChatRoomIdAndReceiverAndDeletedStatusNot(chatRoomId, user, + chatRoomId, user, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); + + chatRoom.delete(); + chatRoomRepository.save(chatRoom); + + if (user.equals(chatRoom.getSender())) { + opsHashMessageRoom.delete(Message_Rooms, chatRoom.getChatRoomId()); + } + + return "대화방을 삭제했습니다."; + } + + public void enterChatRoom(Long receiverId) { + String receiverName = userRepository.findById(receiverId).orElseThrow(UserNotFoundException::new).getUserName(); + ChannelTopic topic = topics.get(receiverName); + + if (topic == null) { + topic = new ChannelTopic(receiverName); + redisMessageListener.addMessageListener(redisSubscriber, topic); + topics.put(receiverName, topic); + } + } + + public ChannelTopic getTopic(Long receiverId) { + String receiverName = userRepository.findById(receiverId).orElseThrow(UserNotFoundException::new).getUserName(); + return topics.get(receiverName); + } +} From a18d233a233b47f7904d01de1fd58ca5afc08150 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:31:39 +0900 Subject: [PATCH 11/28] =?UTF-8?q?feat:=20#17=20ChatRoomController=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20API=20=EC=97=94=EB=93=9C?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 채팅방 생성 API 추가 - 사용자 채팅방 전체 조회 API 추가 - 사용자 채팅방 조회 API 추가 - 채팅방 삭제 API 추가 - JWT 기반 인증 추가 및 사용자 정보 추출 기능 구현 - Swagger를 통한 API 문서화 주석 추가 --- .../controller/ChatRoomController.java | 85 +++++++++++++++++++ .../domain/controller/ChatroomController.java | 12 --- 2 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java delete mode 100644 src/main/java/com/leets/xcellentbe/domain/chatroom/domain/controller/ChatroomController.java diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java new file mode 100644 index 0000000..624ae55 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java @@ -0,0 +1,85 @@ +package com.leets.xcellentbe.domain.chatRoom.controller; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.leets.xcellentbe.domain.chatRoom.dto.ChatRoomDto; +import com.leets.xcellentbe.domain.chatRoom.service.ChatRoomService; +import com.leets.xcellentbe.domain.dm.dto.request.DMRequest; +import com.leets.xcellentbe.domain.dm.dto.response.DMResponse; +import com.leets.xcellentbe.domain.user.domain.User; +import com.leets.xcellentbe.domain.user.domain.repository.UserRepository; +import com.leets.xcellentbe.domain.user.exception.UserNotFoundException; +import com.leets.xcellentbe.global.auth.jwt.JwtService; +import com.leets.xcellentbe.global.response.GlobalResponseDto; + +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/api/chat-room") +@RequiredArgsConstructor +public class ChatRoomController { + + private final ChatRoomService chatRoomService; + private final UserRepository userRepository; + private final JwtService jwtService; // Add JwtService to extract user details + + @PostMapping() + @Operation(summary = "채팅방 생성", description = "채팅방을 생성합니다.") + public ResponseEntity> createChatRoom(@RequestBody DMRequest dmRequest, + @AuthenticationPrincipal UserDetails userDetails) { + String email = userDetails.getUsername(); + User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); + + return ResponseEntity.status(HttpStatus.CREATED) + .body(GlobalResponseDto.success(chatRoomService.createChatRoom(dmRequest, user))); + } + + @GetMapping("/all") + @Operation(summary = "사용자 채팅방 전체 조회", description = "사용자의 모든 채팅방을 조회합니다.") + public ResponseEntity>> findAllChatRoomByUser( + @AuthenticationPrincipal UserDetails userDetails) { + String email = userDetails.getUsername(); + User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); + + List chatRooms = chatRoomService.findAllChatRoomByUser(user); + + return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(chatRooms)); + } + + @GetMapping("/{chatRoomId}") + @Operation(summary = "사용자 채팅방 조회", description = "사용자의 채팅방을 조회합니다.") + public ResponseEntity> findChatRoom(@PathVariable UUID chatRoomId, + @AuthenticationPrincipal UserDetails userDetails) { + String email = userDetails.getUsername(); + User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); + + ChatRoomDto chatRoom = chatRoomService.findChatRoom(chatRoomId, user); + + return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(chatRoom)); + } + + @PatchMapping("/{chatRoomId}") + @Operation(summary = "채팅방 삭제", description = "채팅방을 삭제합니다.") + public ResponseEntity> deleteChatRoom(@PathVariable UUID chatRoomId, + @AuthenticationPrincipal UserDetails userDetails) { + String email = userDetails.getUsername(); + User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); + + return ResponseEntity.status(HttpStatus.OK) + .body(GlobalResponseDto.success(chatRoomService.deleteChatRoom(chatRoomId, user))); + } +} diff --git a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/controller/ChatroomController.java b/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/controller/ChatroomController.java deleted file mode 100644 index 092b246..0000000 --- a/src/main/java/com/leets/xcellentbe/domain/chatroom/domain/controller/ChatroomController.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.leets.xcellentbe.domain.chatroom.domain.controller; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import lombok.RequiredArgsConstructor; - -@RestController -@RequestMapping("/chatroom") -@RequiredArgsConstructor -public class ChatroomController { -} From cb8b8c57f1fe5e687376298447ce87dee620c3a6 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:32:31 +0900 Subject: [PATCH 12/28] =?UTF-8?q?feat:=20#17=20DM=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DMId 필드를 BINARY(16)로 설정하여 UUID 저장 형식 변경 - ChatRoom과의 관계를 업데이트하여 chatRoom_id를 사용하도록 수정 - DM 전송자(sender)와 수신자(receiver) 추가 - DeletedStatus 필드를 EnumType.STRING으로 설정 - DM 객체 생성 메서드(create) 추가 - DM 생성자에 Builder 패턴 적용 - 삭제 메서드(delete) 추가하여 메시지 상태 변경 기능 구현 --- .../leets/xcellentbe/domain/dm/domain/DM.java | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java b/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java index e90ece8..61363f0 100644 --- a/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java @@ -2,13 +2,15 @@ import java.util.UUID; -import com.leets.xcellentbe.domain.chatroom.domain.Chatroom; +import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; import com.leets.xcellentbe.domain.shared.BaseTimeEntity; import com.leets.xcellentbe.domain.shared.DeletedStatus; import com.leets.xcellentbe.domain.user.domain.User; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -17,6 +19,7 @@ import jakarta.persistence.ManyToOne; import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -27,17 +30,22 @@ public class DM extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.UUID) + @Column(columnDefinition = "BINARY(16)") private UUID DMId; @NotNull @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "chatroom_id") - private Chatroom chatRoom; + @JoinColumn(name = "chatRoom_id") + private ChatRoom chatRoom; @NotNull @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "participant_id") - private User participant; + @JoinColumn(name = "sender_id") + private User sender; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "receiver_id") + private User receiver; @NotNull @Column @@ -45,5 +53,29 @@ public class DM extends BaseTimeEntity { @NotNull @Column + @Enumerated(EnumType.STRING) private DeletedStatus deletedStatus; + + public static DM create(User sender, User receiver, ChatRoom chatRoom, String message) { + return DM.builder() + .sender(sender) + .receiver(receiver) + .chatRoom(chatRoom) + .message(message) + .build(); + } + + @Builder + private DM(User sender, User receiver, ChatRoom chatRoom, String message) { + super(); + this.sender = sender; + this.receiver = receiver; + this.chatRoom = chatRoom; + this.message = message; + this.deletedStatus = DeletedStatus.NOT_DELETED; + } + + public void delete() { + this.deletedStatus = DeletedStatus.DELETED; + } } From 1e376a529b98eff3ebd642e791c1fa24c59deb8b Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:32:53 +0900 Subject: [PATCH 13/28] =?UTF-8?q?feat:=20#17=20DMDto=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=B3=80=ED=99=98?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DMDto 클래스 추가: 메시지 전송자(sender)와 수신자(receiver)의 ID, 채팅방 ID(chatRoomId), 메시지 내용(message) 필드 포함 - DM 엔티티를 기반으로 DMDto를 생성하는 생성자 추가 - DM 엔티티로부터 DMDto 객체를 생성하는 정적 메서드 from 추가 --- .../leets/xcellentbe/domain/dm/dto/DMDto.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java b/src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java new file mode 100644 index 0000000..8b1e8e2 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java @@ -0,0 +1,22 @@ +package com.leets.xcellentbe.domain.dm.dto; + +import java.util.UUID; + +import com.leets.xcellentbe.domain.dm.domain.DM; + +public record DMDto( + Long senderId, + Long receiverID, + UUID chatRoomId, + String message) { + + public DMDto(DM dm) { + this(dm.getSender().getUserId(), dm.getReceiver().getUserId(), dm.getChatRoom().getChatRoomId(), + dm.getMessage()); + } + + public static DMDto from(DM dm) { + return new DMDto(dm.getSender().getUserId(), dm.getReceiver().getUserId(), dm.getChatRoom().getChatRoomId(), + dm.getMessage()); + } +} From be1dfd4df095566e51faa85be03548da31d7ede4 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:33:14 +0900 Subject: [PATCH 14/28] =?UTF-8?q?feat:=20#17=20DMRequest=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DMRequest 클래스 추가: DM 메시지를 보내기 위한 수신자(receiver) ID 필드를 포함 --- .../leets/xcellentbe/domain/dm/dto/request/DMRequest.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/dm/dto/request/DMRequest.java diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/dto/request/DMRequest.java b/src/main/java/com/leets/xcellentbe/domain/dm/dto/request/DMRequest.java new file mode 100644 index 0000000..27050a0 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/dm/dto/request/DMRequest.java @@ -0,0 +1,7 @@ +package com.leets.xcellentbe.domain.dm.dto.request; + +public record DMRequest( + Long receiverId) +{ + +} From e5f3226fcaa76bbeb370e22b2f1e317557872489 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:33:35 +0900 Subject: [PATCH 15/28] =?UTF-8?q?feat:=20#17=20DMResponse=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DMResponse 클래스 추가: DM 메시지 응답을 위한 채팅방 ID, 송신자 ID, 수신자 ID, 메시지, 생성일 필드 포함 - 다양한 생성자 추가: 채팅방 정보 또는 송수신자 정보를 기반으로 인스턴스 생성 가능 - 최신 메시지 내용과 생성일 업데이트 메서드 추가 --- .../domain/dm/dto/response/DMResponse.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java b/src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java new file mode 100644 index 0000000..1823a41 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java @@ -0,0 +1,47 @@ +package com.leets.xcellentbe.domain.dm.dto.response; + +import java.time.LocalDateTime; +import java.util.UUID; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; +import com.leets.xcellentbe.domain.user.domain.User; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DMResponse { + private UUID chatRoomId; + private Long senderId; + private Long receiverId; + private String message; + private LocalDateTime createdAt; + + public DMResponse(ChatRoom chatRoom) { + this.chatRoomId = chatRoom.getChatRoomId(); + this.senderId = chatRoom.getSender().getUserId(); + this.receiverId = chatRoom.getReceiver().getUserId(); + } + + public DMResponse(UUID chatRoomId, User sender, User receiver) { + this.chatRoomId = chatRoomId; + this.senderId = sender.getUserId(); + this.receiverId = receiver.getUserId(); + } + + public DMResponse(UUID chatRoomId) { + this.chatRoomId = chatRoomId; + } + + public void updateLatestMessageContent(String message) { + this.message = message; + } + + public void updateLatestMessageCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } +} + From 607fc46d905b2c15336981d0268f232ffb8cbedd Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:34:12 +0900 Subject: [PATCH 16/28] =?UTF-8?q?feat:=20#17=20DMRepository=EC=97=90=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - findTop100ByChatRoomAndDeletedStatusNotOrderByCreatedAtAsc(): 특정 채팅방에서 삭제되지 않은 최신 100개의 메시지를 시간 순으로 조회하는 메서드 추가 - findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(): 특정 채팅방에서 삭제되지 않은 가장 최신 메시지를 조회하는 메서드 추가 --- .../domain/dm/domain/repository/DMRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/domain/repository/DMRepository.java b/src/main/java/com/leets/xcellentbe/domain/dm/domain/repository/DMRepository.java index 2ca8980..d146ead 100644 --- a/src/main/java/com/leets/xcellentbe/domain/dm/domain/repository/DMRepository.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/domain/repository/DMRepository.java @@ -1,10 +1,17 @@ package com.leets.xcellentbe.domain.dm.domain.repository; +import java.util.List; import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; +import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; import com.leets.xcellentbe.domain.dm.domain.DM; +import com.leets.xcellentbe.domain.shared.DeletedStatus; public interface DMRepository extends JpaRepository { + + List findTop100ByChatRoomAndDeletedStatusNotOrderByCreatedAtAsc(ChatRoom chatRoom, DeletedStatus deletedStatus); + + DM findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(ChatRoom chatRoom, DeletedStatus deletedStatus); } From 8bea08597cd7f91973d8ce18c1bcb5d907860380 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:34:46 +0900 Subject: [PATCH 17/28] =?UTF-8?q?feat:=20#17=20ErrorCode=EC=97=90=20DM=5FN?= =?UTF-8?q?OT=5FFOUND=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DM_NOT_FOUND(404, "DM_NOT_FOUND", "메시지를 찾을 수 없습니다."): 메시지를 찾지 못한 경우의 오류 코드 추가 --- src/main/java/com/leets/xcellentbe/global/error/ErrorCode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/leets/xcellentbe/global/error/ErrorCode.java b/src/main/java/com/leets/xcellentbe/global/error/ErrorCode.java index 95a4df6..68324af 100644 --- a/src/main/java/com/leets/xcellentbe/global/error/ErrorCode.java +++ b/src/main/java/com/leets/xcellentbe/global/error/ErrorCode.java @@ -18,6 +18,7 @@ public enum ErrorCode { USER_ALREADY_EXISTS(412, "ALREADY_EXISTS_EXCEPTION", "이미 존재하는 사용자입니다."), ARTICLE_NOT_FOUND(404, "ARTICLE_NOT_FOUND", "게시물을 찾을 수 없습니다."), CHAT_ROOM_NOT_FOUND(404, "CHAT_ROOM_NOT_FOUND", "채팅방을 찾을 수 없습니다."), + DM_NOT_FOUND(404, "DM_NOT_FOUND", "메시지를 찾을 수 없습니다."), REJECT_DUPLICATION(409, "REJECT_DUPLICATION", "중복된 값입니다."), AUTH_CODE_ALREADY_SENT(429, "AUTH_CODE_ALREADY_SENT", "이미 인증번호를 전송했습니다."), INTERNAL_SERVER_ERROR(500, "INTERNAL_SERVER_ERROR", "서버 오류가 발생했습니다."), From 4c1d0cf6476093d94d1af6625a3f09e99bd7a6c8 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:35:12 +0900 Subject: [PATCH 18/28] =?UTF-8?q?feat:=20#17=20DMNotFoundException=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DM_NOT_FOUND 오류 코드 사용하여 메시지를 찾을 수 없는 경우 발생하는 예외 클래스 추가 --- .../domain/dm/exception/DMNotFoundException.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/dm/exception/DMNotFoundException.java diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/exception/DMNotFoundException.java b/src/main/java/com/leets/xcellentbe/domain/dm/exception/DMNotFoundException.java new file mode 100644 index 0000000..4761ee2 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/dm/exception/DMNotFoundException.java @@ -0,0 +1,11 @@ +package com.leets.xcellentbe.domain.dm.exception; + +import com.leets.xcellentbe.global.error.ErrorCode; +import com.leets.xcellentbe.global.error.exception.CommonException; + +public class DMNotFoundException extends CommonException { + + public DMNotFoundException() { + super(ErrorCode.DM_NOT_FOUND); + } +} From b6387fd1d8cf58d587fe9e66a1b297c10dbf38db Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:35:46 +0900 Subject: [PATCH 19/28] =?UTF-8?q?feat:=20#17=20DMService=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=A0=80=EC=9E=A5,=20=EB=A1=9C=EB=93=9C?= =?UTF-8?q?=20=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - saveMessage 메서드를 통해 Redis와 DB에 메시지 저장 - loadMessage 메서드를 통해 Redis에서 메시지를 로드하고, 없을 시 DB에서 조회하여 캐시에 저장 - deleteDM 메서드를 통해 Redis와 DB에서 특정 메시지 삭제 - Redis TTL을 1분으로 설정하여 캐시 최적화 --- .../domain/dm/service/DMService.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java b/src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java new file mode 100644 index 0000000..9a5292f --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java @@ -0,0 +1,104 @@ +package com.leets.xcellentbe.domain.dm.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.stereotype.Service; + +import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; +import com.leets.xcellentbe.domain.chatRoom.domain.repository.ChatRoomRepository; +import com.leets.xcellentbe.domain.chatRoom.exception.ChatRoomNotFoundException; +import com.leets.xcellentbe.domain.dm.domain.DM; +import com.leets.xcellentbe.domain.dm.domain.repository.DMRepository; +import com.leets.xcellentbe.domain.dm.dto.DMDto; +import com.leets.xcellentbe.domain.shared.DeletedStatus; +import com.leets.xcellentbe.domain.user.domain.User; +import com.leets.xcellentbe.domain.user.domain.repository.UserRepository; +import com.leets.xcellentbe.domain.user.exception.UserNotFoundException; +import com.leets.xcellentbe.domain.dm.exception.DMNotFoundException; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class DMService { + + private final RedisTemplate redisTemplateMessage; + private final ChatRoomRepository chatRoomRepository; + private final UserRepository userRepository; + private final DMRepository dmRepository; + + public void saveMessage(DMDto dmDto) { + ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndDeletedStatusNot(dmDto.chatRoomId(), DeletedStatus.DELETED).orElseThrow( + ChatRoomNotFoundException::new); + + User sender = userRepository.findById(dmDto.senderId()).orElseThrow(UserNotFoundException::new); + User receiver = userRepository.findById(dmDto.receiverID()).orElseThrow(UserNotFoundException::new); + String message = dmDto.message(); + + DM dm = DM.create(sender, receiver, chatRoom, message); + dmRepository.save(dm); + + chatRoom.updateLastMessage(message); + chatRoomRepository.save(chatRoom); + + redisTemplateMessage.setValueSerializer(new Jackson2JsonRedisSerializer<>(DM.class)); + + String receiverName = receiver.getUserName(); + + redisTemplateMessage.opsForList().rightPush(receiverName, dmDto); + + redisTemplateMessage.expire(receiverName, 1, TimeUnit.MINUTES); + } + + public List loadMessage(UUID chatRoomId) { + List messageList = new ArrayList<>(); + ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndDeletedStatusNot(chatRoomId, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); + String receiverName = chatRoom.getReceiver().getUserName(); + + List redisMessageList = redisTemplateMessage.opsForList().range(receiverName, 0, 99); + + if (redisMessageList == null || redisMessageList.isEmpty()) { + List dbMessageList = dmRepository.findTop100ByChatRoomAndDeletedStatusNotOrderByCreatedAtAsc(chatRoom, DeletedStatus.DELETED); + + for (DM dm : dbMessageList) { + DMDto messageDto = DMDto.from(dm); + messageList.add(messageDto); + redisTemplateMessage.setValueSerializer(new Jackson2JsonRedisSerializer<>(DM.class)); + redisTemplateMessage.opsForList().rightPush(receiverName, messageDto); + } + } else { + messageList.addAll(redisMessageList); + } + + return messageList; + } + + public String deleteDM(UUID dmId) { + DM dm = dmRepository.findById(dmId).orElseThrow(DMNotFoundException::new); + + dm.delete(); + dmRepository.save(dm); + + String receiverName = dm.getReceiver().getUserName(); + List redisMessageList = redisTemplateMessage.opsForList().range(receiverName, 0, -1); + + if (redisMessageList != null) { + for (DMDto dmDto : redisMessageList) { + if (dmDto.chatRoomId().equals(dm.getChatRoom().getChatRoomId()) && + dmDto.message().equals(dm.getMessage()) && + dmDto.senderId().equals(dm.getSender().getUserId()) && + dmDto.receiverID().equals(dm.getReceiver().getUserId())) { + redisTemplateMessage.opsForList().remove(receiverName, 1, dmDto); + break; + } + } + } + + return "메시지를 삭제했습니다."; + } +} From c78376b102d987caf1542a0e88310f91cdf6ba40 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:36:36 +0900 Subject: [PATCH 20/28] =?UTF-8?q?feat:=20#17=20DMController=20=EC=B1=84?= =?UTF-8?q?=ED=8C=85=20=EC=8B=9C=EC=9E=91,=20=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - @MessageMapping과 @PostMapping을 통한 채팅 시작 메서드 추가 - /api/chat-room/{chatRoomId}/dm 경로에서 채팅방 메시지 로드 기능 구현 - /api/chat-room/delete/{dmId} 경로에서 특정 메시지 삭제 기능 구현 - Redis를 이용한 실시간 메시지 전송 및 캐싱 처리 적용 --- .../domain/dm/controller/DMController.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java b/src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java new file mode 100644 index 0000000..7fc68d1 --- /dev/null +++ b/src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java @@ -0,0 +1,66 @@ +package com.leets.xcellentbe.domain.dm.controller; + +import java.util.List; +import java.util.UUID; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.leets.xcellentbe.domain.chatRoom.service.ChatRoomService; +import com.leets.xcellentbe.domain.dm.dto.DMDto; +import com.leets.xcellentbe.domain.dm.service.DMService; +import com.leets.xcellentbe.global.redis.RedisPublisher; +import com.leets.xcellentbe.global.response.GlobalResponseDto; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class DMController { + + private final RedisPublisher redisPublisher; + private final ChatRoomService chatRoomService; + private final DMService dmService; + + @MessageMapping("/dm") + @Operation(summary = "채팅을 시작", description = "채팅을 시작합니다.") + public void message(DMDto dmDto) { + chatRoomService.enterChatRoom(dmDto.receiverID()); + redisPublisher.publish(chatRoomService.getTopic(dmDto.receiverID()), dmDto); + + dmService.saveMessage(dmDto); + } + + @PostMapping("/dm") + @Operation(summary = "채팅을 시작", description = "채팅을 시작합니다.") + public void startChat( + @Parameter(description = "메시지 전송 객체") @RequestBody DMDto dmDto) { + chatRoomService.enterChatRoom(dmDto.receiverID()); + redisPublisher.publish(chatRoomService.getTopic(dmDto.receiverID()), dmDto); + + dmService.saveMessage(dmDto); + + } + + @GetMapping("/api/chat-room/{chatRoomId}/dm") + @Operation(summary = "채팅방 로드", description = "채팅방을 로드합니다.") + public ResponseEntity>> loadMessage(@PathVariable UUID chatRoomId) { + return ResponseEntity.status(HttpStatus.CREATED) + .body(GlobalResponseDto.success(dmService.loadMessage(chatRoomId))); + } + + @PatchMapping("/api/chat-room/delete/{dmId}") + @Operation(summary = "메시지 삭제", description = "메시지를 삭제합니다.") + public ResponseEntity> deleteDM(@PathVariable UUID dmId) { + return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(dmService.deleteDM(dmId))); + } +} From 37cc095f6afddf0e58707d9eeea1b2c81795cd07 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:38:15 +0900 Subject: [PATCH 21/28] =?UTF-8?q?refactor:=20#17=20=EC=8B=9C=ED=81=90?= =?UTF-8?q?=EB=A6=AC=ED=8B=B0=20=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `/api/chat-room/**`와 `/dm` 엔드포인트 접근을 허용하도록 설정 수정 --- .../java/com/leets/xcellentbe/global/config/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/leets/xcellentbe/global/config/SecurityConfig.java b/src/main/java/com/leets/xcellentbe/global/config/SecurityConfig.java index 677c83e..85e54e1 100644 --- a/src/main/java/com/leets/xcellentbe/global/config/SecurityConfig.java +++ b/src/main/java/com/leets/xcellentbe/global/config/SecurityConfig.java @@ -72,7 +72,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { authorize -> authorize .requestMatchers("/v3/api-docs", "/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", - "/swagger/**", "/index.html", "/api/auth/**").permitAll() + "/swagger/**", "/index.html", "/api/auth/**", "/api/chat-room/**", "/dm").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2.successHandler(oAuthLoginSuccessHandler)); From a9f1d6e7315f6cbe070f69ef1e4f091152c21d4d Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Mon, 4 Nov 2024 12:39:15 +0900 Subject: [PATCH 22/28] =?UTF-8?q?refactor:=20#17=20Swagger=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B5=A8=EB=91=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SecurityRequirement의 이름을 "bearer"에서 "jwt token"으로 수정 - 메서드 이름을 getSecurityRequireMent에서 getSecurityRequirement로 수정하여 일관성 향상 - SecurityScheme 생성 시 메서드 체인 사용하여 가독성 개선 --- .../global/config/swagger/SwaggerConfig.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/leets/xcellentbe/global/config/swagger/SwaggerConfig.java b/src/main/java/com/leets/xcellentbe/global/config/swagger/SwaggerConfig.java index 612f91d..fe168de 100644 --- a/src/main/java/com/leets/xcellentbe/global/config/swagger/SwaggerConfig.java +++ b/src/main/java/com/leets/xcellentbe/global/config/swagger/SwaggerConfig.java @@ -22,7 +22,7 @@ public class SwaggerConfig { @Bean public OpenAPI openAPI() { SecurityScheme securityScheme = getSecurityScheme(); - SecurityRequirement securityRequirement = getSecurityRequireMent(); + SecurityRequirement securityRequirement = getSecurityRequirement(); Server server = new Server(); server.setUrl("/"); @@ -34,11 +34,15 @@ public OpenAPI openAPI() { } private SecurityScheme getSecurityScheme() { - return new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT") - .in(SecurityScheme.In.HEADER).name("Authorization"); + return new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .name("Authorization"); } - private SecurityRequirement getSecurityRequireMent() { - return new SecurityRequirement().addList("bearer"); + private SecurityRequirement getSecurityRequirement() { + return new SecurityRequirement().addList("jwt token"); } } From 91237a078da057a54701a8d5a0e1d8484f1e3551 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Wed, 6 Nov 2024 01:06:47 +0900 Subject: [PATCH 23/28] =?UTF-8?q?refactor:=20DM=20redis=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=ED=8C=8C=EC=9D=BC=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - global -> domain/dm --- .../xcellentbe/domain/chatRoom/service/ChatRoomService.java | 3 ++- .../leets/xcellentbe/domain/dm/controller/DMController.java | 2 +- .../xcellentbe/{global => domain/dm}/redis/RedisPublisher.java | 2 +- .../{global => domain/dm}/redis/RedisSubscriber.java | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) rename src/main/java/com/leets/xcellentbe/{global => domain/dm}/redis/RedisPublisher.java (91%) rename src/main/java/com/leets/xcellentbe/{global => domain/dm}/redis/RedisSubscriber.java (96%) diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java index 1bd8ab2..deab76c 100644 --- a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java @@ -20,11 +20,12 @@ import com.leets.xcellentbe.domain.dm.domain.repository.DMRepository; import com.leets.xcellentbe.domain.dm.dto.request.DMRequest; import com.leets.xcellentbe.domain.dm.dto.response.DMResponse; +import com.leets.xcellentbe.domain.dm.redis.RedisSubscriber; import com.leets.xcellentbe.domain.shared.DeletedStatus; import com.leets.xcellentbe.domain.user.domain.User; import com.leets.xcellentbe.domain.user.domain.repository.UserRepository; import com.leets.xcellentbe.domain.user.exception.UserNotFoundException; -import com.leets.xcellentbe.global.redis.RedisSubscriber; + import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java b/src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java index 7fc68d1..9f036c3 100644 --- a/src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/controller/DMController.java @@ -16,7 +16,7 @@ import com.leets.xcellentbe.domain.chatRoom.service.ChatRoomService; import com.leets.xcellentbe.domain.dm.dto.DMDto; import com.leets.xcellentbe.domain.dm.service.DMService; -import com.leets.xcellentbe.global.redis.RedisPublisher; +import com.leets.xcellentbe.domain.dm.redis.RedisPublisher; import com.leets.xcellentbe.global.response.GlobalResponseDto; import io.swagger.v3.oas.annotations.Operation; diff --git a/src/main/java/com/leets/xcellentbe/global/redis/RedisPublisher.java b/src/main/java/com/leets/xcellentbe/domain/dm/redis/RedisPublisher.java similarity index 91% rename from src/main/java/com/leets/xcellentbe/global/redis/RedisPublisher.java rename to src/main/java/com/leets/xcellentbe/domain/dm/redis/RedisPublisher.java index 5530e7f..416251c 100644 --- a/src/main/java/com/leets/xcellentbe/global/redis/RedisPublisher.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/redis/RedisPublisher.java @@ -1,4 +1,4 @@ -package com.leets.xcellentbe.global.redis; +package com.leets.xcellentbe.domain.dm.redis; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.ChannelTopic; diff --git a/src/main/java/com/leets/xcellentbe/global/redis/RedisSubscriber.java b/src/main/java/com/leets/xcellentbe/domain/dm/redis/RedisSubscriber.java similarity index 96% rename from src/main/java/com/leets/xcellentbe/global/redis/RedisSubscriber.java rename to src/main/java/com/leets/xcellentbe/domain/dm/redis/RedisSubscriber.java index d12df30..475bb23 100644 --- a/src/main/java/com/leets/xcellentbe/global/redis/RedisSubscriber.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/redis/RedisSubscriber.java @@ -1,4 +1,4 @@ -package com.leets.xcellentbe.global.redis; +package com.leets.xcellentbe.domain.dm.redis; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; From e5c2871f340355bdc09a1c16617ea675d26afff5 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Wed, 6 Nov 2024 01:13:45 +0900 Subject: [PATCH 24/28] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java | 1 - .../java/com/leets/xcellentbe/domain/dm/service/DMService.java | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java b/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java index 61363f0..0b8c9d3 100644 --- a/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/domain/DM.java @@ -67,7 +67,6 @@ public static DM create(User sender, User receiver, ChatRoom chatRoom, String me @Builder private DM(User sender, User receiver, ChatRoom chatRoom, String message) { - super(); this.sender = sender; this.receiver = receiver; this.chatRoom = chatRoom; diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java b/src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java index 9a5292f..78c3b3f 100644 --- a/src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/service/DMService.java @@ -46,8 +46,6 @@ public void saveMessage(DMDto dmDto) { chatRoom.updateLastMessage(message); chatRoomRepository.save(chatRoom); - redisTemplateMessage.setValueSerializer(new Jackson2JsonRedisSerializer<>(DM.class)); - String receiverName = receiver.getUserName(); redisTemplateMessage.opsForList().rightPush(receiverName, dmDto); @@ -68,7 +66,6 @@ public List loadMessage(UUID chatRoomId) { for (DM dm : dbMessageList) { DMDto messageDto = DMDto.from(dm); messageList.add(messageDto); - redisTemplateMessage.setValueSerializer(new Jackson2JsonRedisSerializer<>(DM.class)); redisTemplateMessage.opsForList().rightPush(receiverName, messageDto); } } else { From f5b4a566af53ef8743a569ed5dc775533c1c73f8 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Wed, 6 Nov 2024 01:34:23 +0900 Subject: [PATCH 25/28] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EC=B1=85=EC=9E=84=EC=9D=84=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=EC=97=90=EA=B2=8C=20=EC=A0=84?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChatRoomController.java | 32 +++---------- .../chatRoom/service/ChatRoomService.java | 46 ++++++++++++------- 2 files changed, 35 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java index 624ae55..5213d51 100644 --- a/src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/controller/ChatRoomController.java @@ -19,10 +19,6 @@ import com.leets.xcellentbe.domain.chatRoom.service.ChatRoomService; import com.leets.xcellentbe.domain.dm.dto.request.DMRequest; import com.leets.xcellentbe.domain.dm.dto.response.DMResponse; -import com.leets.xcellentbe.domain.user.domain.User; -import com.leets.xcellentbe.domain.user.domain.repository.UserRepository; -import com.leets.xcellentbe.domain.user.exception.UserNotFoundException; -import com.leets.xcellentbe.global.auth.jwt.JwtService; import com.leets.xcellentbe.global.response.GlobalResponseDto; import io.swagger.v3.oas.annotations.Operation; @@ -34,52 +30,36 @@ public class ChatRoomController { private final ChatRoomService chatRoomService; - private final UserRepository userRepository; - private final JwtService jwtService; // Add JwtService to extract user details @PostMapping() @Operation(summary = "채팅방 생성", description = "채팅방을 생성합니다.") public ResponseEntity> createChatRoom(@RequestBody DMRequest dmRequest, @AuthenticationPrincipal UserDetails userDetails) { - String email = userDetails.getUsername(); - User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); - return ResponseEntity.status(HttpStatus.CREATED) - .body(GlobalResponseDto.success(chatRoomService.createChatRoom(dmRequest, user))); + .body(GlobalResponseDto.success(chatRoomService.createChatRoom(dmRequest, userDetails))); } @GetMapping("/all") @Operation(summary = "사용자 채팅방 전체 조회", description = "사용자의 모든 채팅방을 조회합니다.") public ResponseEntity>> findAllChatRoomByUser( @AuthenticationPrincipal UserDetails userDetails) { - String email = userDetails.getUsername(); - User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); - - List chatRooms = chatRoomService.findAllChatRoomByUser(user); - - return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(chatRooms)); + return ResponseEntity.status(HttpStatus.OK) + .body(GlobalResponseDto.success(chatRoomService.findAllChatRoomByUser(userDetails))); } @GetMapping("/{chatRoomId}") @Operation(summary = "사용자 채팅방 조회", description = "사용자의 채팅방을 조회합니다.") public ResponseEntity> findChatRoom(@PathVariable UUID chatRoomId, @AuthenticationPrincipal UserDetails userDetails) { - String email = userDetails.getUsername(); - User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); - - ChatRoomDto chatRoom = chatRoomService.findChatRoom(chatRoomId, user); - - return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(chatRoom)); + return ResponseEntity.status(HttpStatus.OK) + .body(GlobalResponseDto.success(chatRoomService.findChatRoom(chatRoomId, userDetails))); } @PatchMapping("/{chatRoomId}") @Operation(summary = "채팅방 삭제", description = "채팅방을 삭제합니다.") public ResponseEntity> deleteChatRoom(@PathVariable UUID chatRoomId, @AuthenticationPrincipal UserDetails userDetails) { - String email = userDetails.getUsername(); - User user = userRepository.findByEmail(email).orElseThrow(UserNotFoundException::new); - return ResponseEntity.status(HttpStatus.OK) - .body(GlobalResponseDto.success(chatRoomService.deleteChatRoom(chatRoomId, user))); + .body(GlobalResponseDto.success(chatRoomService.deleteChatRoom(chatRoomId, userDetails))); } } diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java index deab76c..a8ff848 100644 --- a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java @@ -10,6 +10,7 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.ChannelTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; @@ -26,7 +27,6 @@ import com.leets.xcellentbe.domain.user.domain.repository.UserRepository; import com.leets.xcellentbe.domain.user.exception.UserNotFoundException; - import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; @@ -52,17 +52,20 @@ private void init() { topics = new HashMap<>(); } - public DMResponse createChatRoom(DMRequest dmRequest, User user) { + public DMResponse createChatRoom(DMRequest dmRequest, UserDetails userDetails) { + User sender = userRepository.findByEmail(userDetails.getUsername()).orElseThrow(UserNotFoundException::new); + User receiver = userRepository.findById(dmRequest.receiverId()).orElseThrow(UserNotFoundException::new); - ChatRoom chatRoom = chatRoomRepository.findBySenderAndReceiverAndDeletedStatusNot(user, receiver, DeletedStatus.DELETED); + ChatRoom chatRoom = chatRoomRepository.findBySenderAndReceiverAndDeletedStatusNot(sender, receiver, + DeletedStatus.DELETED); - if ((chatRoom == null) || (chatRoom != null && (!user.equals(chatRoom.getSender()) && !receiver.equals( + if ((chatRoom == null) || (chatRoom != null && (!sender.equals(chatRoom.getSender()) && !receiver.equals( chatRoom.getReceiver())))) { - ChatRoomDto chatRoomDto = ChatRoomDto.of(dmRequest, user); - opsHashMessageRoom.put(Message_Rooms, user.getUserName(), chatRoomDto); + ChatRoomDto chatRoomDto = ChatRoomDto.of(dmRequest, sender); + opsHashMessageRoom.put(Message_Rooms, sender.getUserName(), chatRoomDto); - chatRoom = chatRoomRepository.save(ChatRoom.create(user, receiver)); + chatRoom = chatRoomRepository.save(ChatRoom.create(sender, receiver)); return new DMResponse(chatRoom); } else { @@ -70,8 +73,11 @@ public DMResponse createChatRoom(DMRequest dmRequest, User user) { } } - public List findAllChatRoomByUser(User user) { - List chatRooms = chatRoomRepository.findBySenderOrReceiverAndDeletedStatusNot(user, user, DeletedStatus.DELETED); + public List findAllChatRoomByUser(UserDetails userDetails) { + User user = userRepository.findByEmail(userDetails.getUsername()).orElseThrow(UserNotFoundException::new); + + List chatRooms = chatRoomRepository.findBySenderOrReceiverAndDeletedStatusNot(user, user, + DeletedStatus.DELETED); List dmRespons = new ArrayList<>(); @@ -91,7 +97,8 @@ public List findAllChatRoomByUser(User user) { chatRoom.getReceiver()); } - latestMessage = dmRepository.findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(chatRoom, DeletedStatus.DELETED); + latestMessage = dmRepository.findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(chatRoom, + DeletedStatus.DELETED); if (latestMessage != null) { messageRoomDto.updateLatestMessageCreatedAt(latestMessage.getCreatedAt()); @@ -104,20 +111,25 @@ public List findAllChatRoomByUser(User user) { return dmRespons; } - public ChatRoomDto findChatRoom(UUID chatRoomId, User user) { - ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndDeletedStatusNot(chatRoomId, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); + public ChatRoomDto findChatRoom(UUID chatRoomId, UserDetails userDetails) { + User user = userRepository.findByEmail(userDetails.getUsername()).orElseThrow(UserNotFoundException::new); + + ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndDeletedStatusNot(chatRoomId, DeletedStatus.DELETED) + .orElseThrow(ChatRoomNotFoundException::new); User receiver = chatRoom.getReceiver(); - chatRoom = chatRoomRepository.findByChatRoomIdAndSenderOrChatRoomIdAndReceiverAndDeletedStatusNot(chatRoomId, user, - chatRoomId, receiver, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); + chatRoom = chatRoomRepository.findByChatRoomIdAndSenderOrChatRoomIdAndReceiverAndDeletedStatusNot(chatRoomId, + user, chatRoomId, receiver, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); return ChatRoomDto.of(chatRoom.getChatRoomId(), chatRoom.getSender(), chatRoom.getReceiver()); } - public String deleteChatRoom(UUID chatRoomId, User user) { - ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndSenderOrChatRoomIdAndReceiverAndDeletedStatusNot(chatRoomId, user, - chatRoomId, user, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); + public String deleteChatRoom(UUID chatRoomId, UserDetails userDetails) { + User user = userRepository.findByEmail(userDetails.getUsername()).orElseThrow(UserNotFoundException::new); + + ChatRoom chatRoom = chatRoomRepository.findByChatRoomIdAndSenderOrChatRoomIdAndReceiverAndDeletedStatusNot( + chatRoomId, user, chatRoomId, user, DeletedStatus.DELETED).orElseThrow(ChatRoomNotFoundException::new); chatRoom.delete(); chatRoomRepository.save(chatRoom); From 93a3f4aabc4021a4a4c55bfa475d5bf779341d17 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Wed, 6 Nov 2024 01:35:07 +0900 Subject: [PATCH 26/28] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F?= =?UTF-8?q?=20=EC=98=A4=ED=83=88=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chatRoom/service/ChatRoomService.java | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java index a8ff848..a5465f9 100644 --- a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java @@ -79,25 +79,17 @@ public List findAllChatRoomByUser(UserDetails userDetails) { List chatRooms = chatRoomRepository.findBySenderOrReceiverAndDeletedStatusNot(user, user, DeletedStatus.DELETED); - List dmRespons = new ArrayList<>(); + List dmResponses = new ArrayList<>(); for (ChatRoom chatRoom : chatRooms) { DMResponse messageRoomDto; - DM latestMessage; - - if (user.equals(chatRoom.getSender())) { - messageRoomDto = new DMResponse( - chatRoom.getChatRoomId(), - chatRoom.getSender(), - chatRoom.getReceiver()); - } else { - messageRoomDto = new DMResponse( - chatRoom.getChatRoomId(), - chatRoom.getSender(), - chatRoom.getReceiver()); - } - latestMessage = dmRepository.findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(chatRoom, + messageRoomDto = new DMResponse( + chatRoom.getChatRoomId(), + chatRoom.getSender(), + chatRoom.getReceiver()); + + DM latestMessage = dmRepository.findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(chatRoom, DeletedStatus.DELETED); if (latestMessage != null) { @@ -105,10 +97,10 @@ public List findAllChatRoomByUser(UserDetails userDetails) { messageRoomDto.updateLatestMessageContent(latestMessage.getMessage()); } - dmRespons.add(messageRoomDto); + dmResponses.add(messageRoomDto); } - return dmRespons; + return dmResponses; } public ChatRoomDto findChatRoom(UUID chatRoomId, UserDetails userDetails) { From def01675d4d729b35dbcecafd6fe08cdd8e324ee Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Wed, 6 Nov 2024 01:41:53 +0900 Subject: [PATCH 27/28] =?UTF-8?q?refactor:=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=ED=95=9C=EC=A0=95=EC=9E=90=EB=A5=BC=20private?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java b/src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java index 8b1e8e2..b3e9389 100644 --- a/src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/dto/DMDto.java @@ -10,7 +10,7 @@ public record DMDto( UUID chatRoomId, String message) { - public DMDto(DM dm) { + private DMDto(DM dm) { this(dm.getSender().getUserId(), dm.getReceiver().getUserId(), dm.getChatRoom().getChatRoomId(), dm.getMessage()); } From 26712b2673f0b6787eb55576d6e04063b26f6850 Mon Sep 17 00:00:00 2001 From: yechan-kim <60172300+yechan-kim@users.noreply.github.com> Date: Wed, 6 Nov 2024 01:51:12 +0900 Subject: [PATCH 28/28] =?UTF-8?q?refactor:=20DMResponse=EC=97=90=20Builder?= =?UTF-8?q?=20=ED=8C=A8=ED=8B=B4=20=EB=B0=8F=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=ED=8E=99=ED=86=A0=EB=A6=AC=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chatRoom/service/ChatRoomService.java | 13 +++---- .../domain/dm/dto/response/DMResponse.java | 36 +++++++++++++------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java index a5465f9..461d255 100644 --- a/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java +++ b/src/main/java/com/leets/xcellentbe/domain/chatRoom/service/ChatRoomService.java @@ -60,16 +60,16 @@ public DMResponse createChatRoom(DMRequest dmRequest, UserDetails userDetails) { ChatRoom chatRoom = chatRoomRepository.findBySenderAndReceiverAndDeletedStatusNot(sender, receiver, DeletedStatus.DELETED); - if ((chatRoom == null) || (chatRoom != null && (!sender.equals(chatRoom.getSender()) && !receiver.equals( - chatRoom.getReceiver())))) { + if ((chatRoom == null) || (!sender.equals(chatRoom.getSender()) && !receiver.equals( + chatRoom.getReceiver()))) { ChatRoomDto chatRoomDto = ChatRoomDto.of(dmRequest, sender); opsHashMessageRoom.put(Message_Rooms, sender.getUserName(), chatRoomDto); chatRoom = chatRoomRepository.save(ChatRoom.create(sender, receiver)); - return new DMResponse(chatRoom); + return DMResponse.from(chatRoom); } else { - return new DMResponse(chatRoom.getChatRoomId()); + return DMResponse.from(chatRoom.getChatRoomId()); } } @@ -84,10 +84,7 @@ public List findAllChatRoomByUser(UserDetails userDetails) { for (ChatRoom chatRoom : chatRooms) { DMResponse messageRoomDto; - messageRoomDto = new DMResponse( - chatRoom.getChatRoomId(), - chatRoom.getSender(), - chatRoom.getReceiver()); + messageRoomDto = DMResponse.of(chatRoom.getChatRoomId(), chatRoom.getSender(), chatRoom.getReceiver()); DM latestMessage = dmRepository.findTopByChatRoomAndDeletedStatusNotOrderByCreatedAtDesc(chatRoom, DeletedStatus.DELETED); diff --git a/src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java b/src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java index 1823a41..353f5c8 100644 --- a/src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java +++ b/src/main/java/com/leets/xcellentbe/domain/dm/dto/response/DMResponse.java @@ -7,6 +7,7 @@ import com.leets.xcellentbe.domain.chatRoom.domain.ChatRoom; import com.leets.xcellentbe.domain.user.domain.User; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -20,20 +21,35 @@ public class DMResponse { private String message; private LocalDateTime createdAt; - public DMResponse(ChatRoom chatRoom) { - this.chatRoomId = chatRoom.getChatRoomId(); - this.senderId = chatRoom.getSender().getUserId(); - this.receiverId = chatRoom.getReceiver().getUserId(); + @Builder + private DMResponse(UUID chatRoomId, Long senderId, Long receiverId, String message, LocalDateTime createdAt) { + this.chatRoomId = chatRoomId; + this.senderId = senderId; + this.receiverId = receiverId; + this.message = message; + this.createdAt = createdAt; } - public DMResponse(UUID chatRoomId, User sender, User receiver) { - this.chatRoomId = chatRoomId; - this.senderId = sender.getUserId(); - this.receiverId = receiver.getUserId(); + public static DMResponse from(UUID chatRoomId) { + return builder() + .chatRoomId(chatRoomId) + .build(); } - public DMResponse(UUID chatRoomId) { - this.chatRoomId = chatRoomId; + public static DMResponse from(ChatRoom chatRoom) { + return builder() + .chatRoomId(chatRoom.getChatRoomId()) + .senderId(chatRoom.getSender().getUserId()) + .receiverId(chatRoom.getReceiver().getUserId()) + .build(); + } + + public static DMResponse of(UUID chatRoomId, User sender, User receiver) { + return builder() + .chatRoomId(chatRoomId) + .senderId(sender.getUserId()) + .receiverId(receiver.getUserId()) + .build(); } public void updateLatestMessageContent(String message) {