Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 30 additions & 33 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,70 +24,67 @@ repositories {
}

dependencies {
// Spring Boot Starter Dependencies
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.boot:spring-boot-starter'

//open feign
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign', version: '4.1.3'
// OpenFeign for HTTP client communication
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.3'
implementation 'org.springframework.cloud:spring-cloud-commons:4.1.4'

//ELK 연동을 위한 외부 기술
// ELK integration
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
implementation 'net.logstash.logback:logstash-logback-encoder:7.0' // Logstash용 로그백 엔코더
implementation 'net.logstash.logback:logstash-logback-encoder:7.0'

//STOMP ( Websocket )
// WebSocket
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.springframework.boot:spring-boot-starter'

//AWS 관련
// AWS SDK
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.563' // 최신 버전 확인 필요

//추후에 지울 것
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
//

// Spring Security 의존성 추가
// implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.563'

//DB 관련 설정들
// Database & Serialization
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
// implementation 'org.springframework.boot:spring-boot-starter-data-redis'
runtimeOnly 'com.mysql:mysql-connector-j:8.0.33'

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.mysql:mysql-connector-j'
//Swagger Ui
// OpenAPI Documentation
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'


// Jakarta Persistence (for JPA)
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
implementation 'jakarta.validation:jakarta.validation-api:3.0.2'
implementation 'org.springframework.boot:spring-boot-starter-security'

// JWT for Authentication
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' // for JSON serialization/deserialization
implementation 'mysql:mysql-connector-java:8.0.33'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'

// OAuth2 Client Support
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

// Mail Support
implementation 'org.springframework.boot:spring-boot-starter-mail'

// Thymeleaf Template Engine
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-webflux' // WebClient 및 WebFlux 지원

// Redis 관련 의존성
implementation 'org.springframework.boot:spring-boot-starter-data-redis' // redis
runtimeOnly 'com.mysql:mysql-connector-j' // sql
// WebFlux & Reactive Programming
implementation 'org.springframework.boot:spring-boot-starter-webflux'

// Redis Support
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

// Lombok for code generation
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok:1.18.28' // 테스트

// Testing Dependencies
testCompileOnly 'org.projectlombok:lombok:1.18.28'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

runtimeOnly 'com.mysql:mysql-connector-j'
}

tasks.named('test') {
Expand Down
11 changes: 5 additions & 6 deletions src/main/java/com/petmatz/api/chatting/ChatController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.petmatz.api.chatting.dto.*;
import com.petmatz.api.global.dto.Response;
import com.petmatz.api.global.utils.SendChatMessage;
import com.petmatz.common.security.utils.JwtExtractProvider;
import com.petmatz.domain.chatting.ChatMessageService;
import com.petmatz.domain.chatting.ChatRoomService;
Expand Down Expand Up @@ -33,24 +34,22 @@
public class ChatController {

private final ChatMessageService chatService;
private final SimpMessagingTemplate simpMessagingTemplate;
private final UserService userService;
private final ChatRoomService chatRoomService;
private final JwtExtractProvider jwtExtractProvider;
private final SendChatMessage sendChatMessage;

@MessageMapping("/chat")
public void sendPrivateMessage(ChatMessageRequest chatMessageRequest) {
ChatMessageInfo chatMessageInfo = chatMessageRequest.of();
chatService.updateMessage(chatMessageInfo, chatMessageRequest.chatRoomId());
String destination = "/topic/chat/" + chatMessageRequest.chatRoomId();
simpMessagingTemplate.convertAndSend(destination, chatMessageInfo);
sendChatMessage.sendChatMessage(chatMessageRequest.chatRoomId(), chatMessageInfo);
}

@MessageMapping("/chat/{chatRoomId}/read")
public void sendReadStatus(@Payload ChatReadStatusDirect chatReadStatusDirect,
@DestinationVariable String chatRoomId) {
String destination = "/topic/chat/" + chatRoomId;
simpMessagingTemplate.convertAndSend(destination, chatReadStatusDirect);
sendChatMessage.sendChatMessage(chatRoomId, chatReadStatusDirect);
}


Expand All @@ -69,7 +68,7 @@ public Response<ChatMessageResponse> selectChatMessage(
@RequestParam(defaultValue = "1") int startPage
) {
String userEmail = jwtExtractProvider.findAccountIdFromJwt();
String receiverEmail = chatRoomService.selectChatRoomUserInfo(chatRoomId, userEmail);
String receiverEmail = chatRoomService.selectChatRoomUserEmail(chatRoomId, userEmail);
Page<ChatMessageInfo> chatMessageInfos = chatService.selectMessage(receiverEmail, chatRoomId, startPage, pageSize, lastFetchTimestamp);
UserInfo userInfo = userService.selectUserInfo(receiverEmail);

Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/petmatz/api/chatting/MatchingController.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ public Response<List<ChatRoomMetaDataInfoResponse>> chatRoomsList(
) {
String userEmail = jwtExtractProvider.findAccountIdFromJwt();

return Response.success(
chatRoomService.selectChatRoomList(pageSize, startPage, userEmail).stream()
.map(ChatRoomMetaDataInfoResponse::of)
.collect(Collectors.toList())
);
List<ChatRoomMetaDataInfoResponse> chatRoomMetaDataInfoResponseList = chatRoomService.selectChatRoomList(pageSize, startPage, userEmail).stream()
.map(ChatRoomMetaDataInfoResponse::of)
.collect(Collectors.toList());

return Response.success(chatRoomMetaDataInfoResponseList);
}

@DeleteMapping
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/petmatz/api/global/utils/SendChatMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.petmatz.api.global.utils;

import com.petmatz.api.chatting.dto.ChatReadStatusDirect;
import com.petmatz.domain.chatting.dto.ChatMessageInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class SendChatMessage {

private final static String DESTINATION = "/topic/chat/";

private final SimpMessagingTemplate simpMessagingTemplate;


public void sendChatMessage(String chatRoomId, ChatMessageInfo chatMessageInfo) {
String destination = DESTINATION + chatRoomId;
simpMessagingTemplate.convertAndSend(destination, chatMessageInfo);
}

public void sendChatMessage(String chatRoomId, ChatReadStatusDirect chatReadStatusDirect) {
String destination = DESTINATION + chatRoomId;
simpMessagingTemplate.convertAndSend(destination, chatReadStatusDirect);
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.petmatz.api.petmission;

import com.petmatz.api.global.dto.Response;
import com.petmatz.api.global.utils.SendChatMessage;
import com.petmatz.api.petmission.dto.*;
import com.petmatz.common.constants.PetMissionStatusZip;
import com.petmatz.common.security.utils.JwtExtractProvider;
Expand Down Expand Up @@ -29,9 +30,9 @@
public class PetMissionController {

private final PetMissionService petMissionService;
private final SimpMessagingTemplate simpMessagingTemplate;
private final ChatMessageService chatService;
private final UserService userService;
private final SendChatMessage sendChatMessage;

private final JwtExtractProvider jwtExtractProvider;

Expand All @@ -53,16 +54,14 @@ public Response<PetMissionResponse> savePetMissionList(@RequestBody PetMissionRe

chatService.updateMessage(petMissionRequest.ofto(), petMissionData, receiverEmail);

String destination = "/topic/chat/" + petMissionData.chatRoomId();
//채팅 메세지에 UUID 담아서 보내기
ChatMessageInfo chatMessageInfo = petMissionRequest.of(petMissionData.petMissionId(), careEmail,receiverEmail);

PetMissionResponse petMissionResponse = PetMissionResponse.of(petMissionData);
simpMessagingTemplate.convertAndSend(destination, chatMessageInfo);
sendChatMessage.sendChatMessage(petMissionData.chatRoomId(), chatMessageInfo);
return Response.success(petMissionResponse);
}

//TODO 리펙토링 필수임 쿼리문 그지 같음 지금
@Operation(summary = "멍멍이의 부탁 리스트 조회", description = "멍멍이 리스트 조회 API")
@GetMapping
public Response<List<UserToPetMissionListInfo>> selectPetMissionList() {
Expand All @@ -89,9 +88,8 @@ public Response<Void> updatePetMissionStatus(@RequestBody PetMissionUpdateReques
String chatRoomId = petMissionService.selectChatRoomId(petMissionDetails.careEmail(), petMissionDetails.receiverEmail());
ChatMessageInfo chatMessageInfo = petMissionUpdateRequest.of(petMissionUpdateRequest.petMissionId());
chatService.updateMessage(petMissionUpdateRequest.of(petMissionUpdateRequest.petMissionId()), chatRoomId);
String destination = "/topic/chat/" + chatRoomId;
//채팅 메세지에 UUID 담아서 보내기
simpMessagingTemplate.convertAndSend(destination, chatMessageInfo);
sendChatMessage.sendChatMessage(chatRoomId, chatMessageInfo);
return Response.success("업데이트가 정상적으로 되었습니다.");
}
return Response.success("업데이트가 정상적으로 되었습니다.");
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/petmatz/domain/aws/Prefix.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static String returnKoreaName(String name) {
return value.koreaName;
}
}
//TODO 에러 발생 시키기
return "없음";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.petmatz.domain.chatting;

import com.petmatz.api.chatting.dto.ChatReadStatusDirect;
import com.petmatz.domain.chatting.component.ChatMessageReader;
import com.petmatz.domain.chatting.component.ChatMessageUpdater;
import com.petmatz.domain.chatting.docs.ChatReadStatusDocs;
Expand All @@ -10,6 +11,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
Expand All @@ -20,10 +22,12 @@
@RequiredArgsConstructor
public class ChatMessageService {


private final ChatMessageReader chatMessageReader;
private final ChatMessageUpdater chatMessageUpdater;



public Page<ChatMessageInfo> selectMessage(String receiver, String chatRoomsId, int pageNumber, int pageSize, LocalDateTime lastFetchTimestamp) {
// 페이징된 메시지 가져오기
List<ChatMessageInfo> chatMessageInfos = chatMessageReader.selectChatMessagesHistory(chatRoomsId, pageNumber, pageSize,lastFetchTimestamp);
Expand Down Expand Up @@ -56,5 +60,4 @@ public void updateMessage(ChatMessagePetMissionInfo chatMessageInfo, PetMissionD
chatMessageUpdater.updateMessage(chatMessageInfo.of(receiverEmail, petMissionData.petMissionId()),petMissionData.chatRoomId());
}


}
28 changes: 12 additions & 16 deletions src/main/java/com/petmatz/domain/chatting/ChatRoomService.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,10 @@ public class ChatRoomService {
private final ChatRoomMetaDataDeleter chatRoomMetaDataDeleter;
private final ChatReadStatusDeleter chatReadStatusDeleter;

// private final JwtExtractProvider jwtExtractProvider;



//채팅방 신규 생성, 존재시 해당 ChatRoomID 반환
public long createdChatRoom(ChatRoomInfo chatRoomInfo) {
Optional<ChatRoomEntity> chatRoomEntity = chatRoomReader.selectChatRoom(chatRoomInfo);
System.out.println(chatRoomEntity.toString());

if (chatRoomEntity.isPresent()) {
return chatRoomEntity.get().getId();
Expand Down Expand Up @@ -69,18 +65,18 @@ public List<ChatRoomMetaDataInfo> selectChatRoomList(int pageSize, int startPage

private Map<String, IChatUserInfo> getUserList(List<UserToChatRoomEntity> chatRoomNumber, String userEmail) {
Map<String, IChatUserInfo> userList = new HashMap<>();

for (UserToChatRoomEntity userToChatRoomEntity : chatRoomNumber) {
List<UserToChatRoomEntity> participants = userToChatRoomEntity.getChatRoom().getParticipants();
// 현재 사용자가 아닌 다른 사용자를 찾음
for (UserToChatRoomEntity participant : participants) {
if (!participant.getUser().getAccountId().equals(userEmail)) {
IChatUserInfo userInfo = IChatUserInfo.of(
participant.getUser()
);
userList.put(userToChatRoomEntity.getChatRoom().getId().toString(), userInfo);
break; // 다른 참여자를 하나만 찾으면 됨
}
}
String chatRoomId = userToChatRoomEntity.getChatRoom().getId().toString();

// 현재 사용자가 아닌 다른 사용자를 찾기 위한 스트림 사용
userToChatRoomEntity.getChatRoom().getParticipants().stream()
.filter(participant -> !participant.getUser().getAccountId().equals(userEmail))
.findFirst() // 첫 번째로 조건을 만족하는 사용자 찾기
.ifPresent(participant -> {
IChatUserInfo userInfo = IChatUserInfo.of(participant.getUser());
userList.put(chatRoomId, userInfo);
});
}
return userList;
}
Expand Down Expand Up @@ -108,7 +104,7 @@ public void deletRoom(String roomId) {
chatReadStatusDeleter.deleteChatReadStatusDocs(strings, roomId);
}

public String selectChatRoomUserInfo(String chatRoomId, String userEmail) {
public String selectChatRoomUserEmail(String chatRoomId, String userEmail) {
List<String> userEmailList = chatRoomReader.selectChatRoomUserList(chatRoomId);
if (userEmailList.isEmpty()) {
throw new NullPointerException("해당 채팅방이 존재하지 않습니다.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
@RequiredArgsConstructor
public class WebSocketEventListener {

private final static String PATTERN = "/topic/chat/(\\S+)/(\\S+)";
private final static Pattern R = Pattern.compile(PATTERN);
private final static Pattern R = Pattern.compile("/topic/chat/(\\S+)/(\\S+)");


//TODO 여기 의존 바꿔야 할 수도
Expand Down