-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #95 from TeamSynergyy/feature/websocket
#94 WebSocket 을 활용한 채팅 기능
- Loading branch information
Showing
18 changed files
with
560 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
src/main/java/com/seoultech/synergybe/domain/chat/WebSocketConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.seoultech.synergybe.domain.chat; | ||
|
||
import com.seoultech.synergybe.domain.chat.handler.ChatHandler; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.web.socket.config.annotation.*; | ||
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; | ||
|
||
@Configuration | ||
@RequiredArgsConstructor | ||
@EnableWebSocket | ||
public class WebSocketConfig implements WebSocketConfigurer { | ||
private final ChatHandler chatHandler; | ||
|
||
@Override | ||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { | ||
registry.addHandler(chatHandler, "/ws") | ||
.addInterceptors(new HttpSessionHandshakeInterceptor()) | ||
.setAllowedOrigins("*"); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/com/seoultech/synergybe/domain/chat/controller/ChatMessageController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.seoultech.synergybe.domain.chat.controller; | ||
|
||
import com.seoultech.synergybe.domain.chat.domain.ChatMessage; | ||
import com.seoultech.synergybe.domain.chat.service.ChatMessageService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.util.List; | ||
|
||
@RestController | ||
@RequestMapping("/api/v1/chat") | ||
@RequiredArgsConstructor | ||
public class ChatMessageController { | ||
private final ChatMessageService chatMessageService; | ||
|
||
@GetMapping("/{chatRoomId}") | ||
public List<ChatMessage> getChatList(@PathVariable("chatRoomId") Long chatRoomId) { | ||
|
||
return chatMessageService.getChatListByChatRoomId(chatRoomId); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/com/seoultech/synergybe/domain/chat/controller/ChatRoomController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.seoultech.synergybe.domain.chat.controller; | ||
|
||
import com.seoultech.synergybe.domain.chat.domain.ChatRoom; | ||
import com.seoultech.synergybe.domain.chat.dto.request.CreateChatRoomRequest; | ||
import com.seoultech.synergybe.domain.chat.dto.response.GetChatRoomResponse; | ||
import com.seoultech.synergybe.domain.chat.service.ChatRoomService; | ||
import com.seoultech.synergybe.system.config.login.LoginUser; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.util.List; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/v1/rooms") | ||
public class ChatRoomController { | ||
private final ChatRoomService chatRoomService; | ||
|
||
@PostMapping | ||
public ResponseEntity<Void> createChatRoom(@Valid @RequestBody CreateChatRoomRequest request) { | ||
chatRoomService.createRoom(request); | ||
|
||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@GetMapping | ||
public ResponseEntity<List<GetChatRoomResponse>> getChatRoomList(@LoginUser String userId) { | ||
|
||
return ResponseEntity.status(HttpStatus.OK).body(chatRoomService.getChatRoomsByUserId(userId)); | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
src/main/java/com/seoultech/synergybe/domain/chat/domain/ChatMessage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.seoultech.synergybe.domain.chat.domain; | ||
|
||
import jakarta.persistence.Id; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import org.springframework.data.mongodb.core.index.Indexed; | ||
import org.springframework.data.mongodb.core.mapping.Document; | ||
import org.springframework.data.mongodb.core.mapping.Field; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Document(collection = "chat_message") | ||
@Getter | ||
public class ChatMessage { | ||
@Id | ||
@Field("_id") | ||
private String id; | ||
|
||
@Indexed | ||
private Long chatRoomId; | ||
|
||
private String message; | ||
|
||
private String userId; | ||
|
||
private ChatType chatType; | ||
|
||
private String imageName; | ||
|
||
private String imageUrl; | ||
private LocalDateTime createAt; | ||
|
||
@Builder | ||
public ChatMessage(Long chatRoomId, String message, String userId, ChatType chatType, String imageName, String imageUrl, | ||
LocalDateTime createAt) { | ||
this.chatRoomId = chatRoomId; | ||
this.message = message; | ||
this.userId = userId; | ||
this.chatType = chatType; | ||
this.imageName = imageName; | ||
this.imageUrl = imageUrl; | ||
this.createAt = createAt; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
src/main/java/com/seoultech/synergybe/domain/chat/domain/ChatRoom.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package com.seoultech.synergybe.domain.chat.domain; | ||
|
||
import com.seoultech.synergybe.domain.user.User; | ||
import jakarta.persistence.*; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity(name = "chat_room") | ||
@Getter | ||
@NoArgsConstructor | ||
public class ChatRoom { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
@Column(name = "chat_room_id") | ||
private Long id; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "create_user_id", nullable = false) | ||
private User createUser; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "attend_user_id", nullable = false) | ||
private User attendUser; | ||
|
||
@Column(name = "name") | ||
private String name; | ||
|
||
|
||
@Builder | ||
public ChatRoom(User createUser, User attendUser, String name) { | ||
this.createUser = createUser; | ||
this.attendUser = attendUser; | ||
this.name = name; | ||
} | ||
|
||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/seoultech/synergybe/domain/chat/domain/ChatType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.seoultech.synergybe.domain.chat.domain; | ||
|
||
public enum ChatType { | ||
ENTER, | ||
TEXT, | ||
IMAGE | ||
} |
22 changes: 22 additions & 0 deletions
22
src/main/java/com/seoultech/synergybe/domain/chat/dto/request/ChatMessageRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.seoultech.synergybe.domain.chat.dto.request; | ||
|
||
import com.seoultech.synergybe.domain.chat.domain.ChatType; | ||
import jakarta.validation.constraints.NotBlank; | ||
|
||
public record ChatMessageRequest( | ||
@NotBlank | ||
Long chatRoomId, | ||
|
||
@NotBlank | ||
String userId, | ||
|
||
@NotBlank | ||
String message, | ||
|
||
@NotBlank | ||
ChatType chatType, | ||
|
||
String imageName, | ||
String imageUrl | ||
) { | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/seoultech/synergybe/domain/chat/dto/request/CreateChatRoomRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.seoultech.synergybe.domain.chat.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
|
||
public record CreateChatRoomRequest( | ||
@NotBlank(message = "채팅방 생성 유저 ID는 필수값입니다.") | ||
String createUserId, | ||
@NotBlank(message = "채팅방 참석 유저 ID는 필수값입니다.") | ||
String attendUserId, | ||
String roomName | ||
|
||
) { | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/seoultech/synergybe/domain/chat/dto/response/GetChatRoomResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.seoultech.synergybe.domain.chat.dto.response; | ||
|
||
public record GetChatRoomResponse( | ||
Long chatRoomId, | ||
String chatRoomName | ||
) { | ||
} |
141 changes: 141 additions & 0 deletions
141
src/main/java/com/seoultech/synergybe/domain/chat/handler/ChatHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package com.seoultech.synergybe.domain.chat.handler; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.seoultech.synergybe.domain.chat.domain.ChatType; | ||
import com.seoultech.synergybe.domain.chat.dto.request.ChatMessageRequest; | ||
import com.seoultech.synergybe.domain.chat.service.ChatMessageService; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.socket.CloseStatus; | ||
import org.springframework.web.socket.TextMessage; | ||
import org.springframework.web.socket.WebSocketSession; | ||
import org.springframework.web.socket.handler.TextWebSocketHandler; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@Slf4j | ||
@Component | ||
//@RequiredArgsConstructor | ||
public class ChatHandler extends TextWebSocketHandler { | ||
// private static List<WebSocketSession> webSocketSessions = new ArrayList<>(); | ||
private WebSocketSessionMap webSocketSessionMap; // 채팅방별 세션리스트 모음 | ||
private ObjectMapper objectMapper; | ||
private ChatMessageService chatMessageService; | ||
|
||
|
||
|
||
// 채팅 핸들러 생성 | ||
public ChatHandler(ObjectMapper objectMapper, ChatMessageService chatMessageService) { | ||
this.webSocketSessionMap = new WebSocketSessionMap(); | ||
this.objectMapper = objectMapper; | ||
this.chatMessageService = chatMessageService; | ||
} | ||
|
||
@Override | ||
public void afterConnectionEstablished(WebSocketSession session) throws Exception { | ||
// webSocketSessions.add(session); | ||
Long chatRoomId = webSocketSessionMap.getKeyFromSession(session); | ||
|
||
// 여기서 request를 어떻게 알지 ? | ||
if (chatRoomId == null) { | ||
// 채팅방 생성 | ||
// chatRoomService.createRoom(); | ||
} | ||
|
||
|
||
// log.info("session add : " + session.getId()); | ||
} | ||
|
||
@Override | ||
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { | ||
String payLoad = message.getPayload(); | ||
log.info("pay load {}", payLoad); | ||
|
||
// 채팅 Dto로 변환 | ||
ChatMessageRequest chatMessageRequest = objectMapper.readValue(payLoad, ChatMessageRequest.class); | ||
log.info("session {}", chatMessageRequest.toString()); | ||
|
||
// payload에 chatroomId 가져옴 | ||
Long chatRoomId = chatMessageRequest.chatRoomId(); | ||
|
||
Map<Long, WebSocketSessionList> chatRoomSessionMap = webSocketSessionMap.getWebsocketListHashMap(); | ||
|
||
|
||
// 현재 채팅방의 세션이 존재하는지 체크 | ||
if (!chatRoomSessionMap.containsKey(chatRoomId)) { | ||
// 만약 없다면 세션 생성 | ||
WebSocketSessionList webSocketSessionList = WebSocketSessionList.builder() | ||
.webSocketSessions(new ArrayList<>()) | ||
.build(); | ||
|
||
// 생성한 세션에 채팅방 Id와 세션을 Map에 저장 | ||
chatRoomSessionMap.put(chatRoomId, webSocketSessionList); | ||
} | ||
|
||
// 해당 채팅방에 해당하는 세션을 Map에서 가져옴 | ||
WebSocketSessionList webSocketSessionList = chatRoomSessionMap.get(chatRoomId); | ||
|
||
// 만약 입장하는 경우라면 (Type이 Enter 라면) | ||
if (chatMessageRequest.chatType().equals(ChatType.ENTER)) { | ||
// afterConnectionEstablished(session); | ||
// 현재 들어온 세션을 해당 채팅방 세션리스트에 추가 | ||
webSocketSessionList.getWebSocketSessions().add(session); | ||
log.info("session add / session Id : {}", session.getId()); | ||
} | ||
|
||
// 만약 텍스트를 보낸다면 | ||
if (chatMessageRequest.chatType().equals(ChatType.TEXT)) { | ||
// 채팅 전송 | ||
sendAndSaveMessageToChatRoom(chatMessageRequest, webSocketSessionList); | ||
} | ||
|
||
} | ||
|
||
|
||
|
||
@Override | ||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { | ||
Long chatRoomId = webSocketSessionMap.getKeyFromSession(session); | ||
|
||
|
||
|
||
// 얘가 호출되니까 여기서 removeClosedSession을 호출해야지 | ||
// 그런데 roomId로 해당하는 채팅방의 채팅세션리스트들을 가져와야하는데 ? | ||
// 그 내용을 넣어줄 수 있을까 ? | ||
|
||
// 채팅방 리스트 가져오기 내가 가지고 있는 정보는 현재 session 정보임 | ||
List<WebSocketSession> webSocketSessions = getSessionListByChatRoomId(chatRoomId); | ||
webSocketSessions.remove(session); | ||
|
||
log.info("session remove / session Id : {}", session.getId()); | ||
} | ||
|
||
private List<WebSocketSession> getSessionListByChatRoomId(Long chatRoomId) { | ||
return webSocketSessionMap.getWebsocketListHashMap().get(chatRoomId).getWebSocketSessions(); | ||
} | ||
|
||
private void sendAndSaveMessageToChatRoom(ChatMessageRequest chatMessageRequest, WebSocketSessionList webSocketSessionList) { | ||
for (WebSocketSession session : webSocketSessionList.getWebSocketSessions()) { | ||
sendMessage(session, chatMessageRequest.message()); | ||
saveMessage(chatMessageRequest); | ||
} | ||
|
||
// webSocketSessionList.getWebSocketSessions().parallelStream().forEach(sess -> sendMessage(sess, chatMessageRequest.message())); | ||
|
||
} | ||
|
||
private void saveMessage(ChatMessageRequest chatMessageRequest) { | ||
chatMessageService.saveChat(chatMessageRequest); | ||
} | ||
|
||
private <T> void sendMessage(WebSocketSession session, T message) { | ||
try { | ||
session.sendMessage(new TextMessage(objectMapper.writeValueAsString(message))); | ||
} catch (IOException e) { | ||
log.error(e.getMessage(), e); | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/main/java/com/seoultech/synergybe/domain/chat/handler/WebSocketSessionList.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.seoultech.synergybe.domain.chat.handler; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
import org.springframework.web.socket.WebSocketSession; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
public class WebSocketSessionList { | ||
private List<WebSocketSession> webSocketSessions; | ||
|
||
@Builder | ||
public WebSocketSessionList(List<WebSocketSession> webSocketSessions) { | ||
this.webSocketSessions = webSocketSessions; | ||
} | ||
|
||
// 해당 세션을 포함하는지 확인하는 메서드 | ||
public boolean contains(WebSocketSession session) { | ||
return webSocketSessions.contains(session); | ||
} | ||
} |
Oops, something went wrong.