Skip to content

Commit

Permalink
[FEAT] 채팅 기능 추가 (#28)
Browse files Browse the repository at this point in the history
* [FEAT] 채팅 기능 구현

* [FEAT] 채팅방 입장 시 이전 메시지 불러오기

* [FEAT] 채팅방 생성, 리스트 불러올 때 유저 정보에 따라
  • Loading branch information
sangminee authored Feb 28, 2024
1 parent 4d603d5 commit 3e5dfd0
Show file tree
Hide file tree
Showing 34 changed files with 6,623 additions and 5 deletions.
17 changes: 17 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
</properties>
<dependencies>

<!-- chat -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-stomp</artifactId>
<version>5.3.2.RELEASE</version>
</dependency>

<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/com/oya/kr/chat/StompConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.oya.kr.chat;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
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;

import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSocketMessageBroker
@RequiredArgsConstructor
@ComponentScan(basePackages = {"com.oya.kr.global"})
public class StompConfig implements WebSocketMessageBrokerConfigurer {

// private final StompHandler stompHandler;

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic"); //sub으로 시작되는 요청을 구독한 모든 사용자들에게 메시지를 broadcast한다.
config.setApplicationDestinationPrefixes("/app"); // pub로 시작되는 메시지는 message-handling methods로 라우팅된다.
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*")
.withSockJS(); // sock.js를 통하여 낮은 버전의 브라우저에서도 websocket이 동작할수 있게 설정
// registry.addEndpoint("/ws").setAllowedOrigins("*"); // api 통신 시, withSockJS() 설정을 빼야됨
}

// @Override
// public void configureClientInboundChannel(ChannelRegistration registration) {
// registration.interceptors(stompHandler);
// }
}
78 changes: 78 additions & 0 deletions src/main/java/com/oya/kr/chat/controller/ChatRoomController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.oya.kr.chat.controller;

import java.security.Principal;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.oya.kr.chat.controller.dto.response.ChatRoomAndMessageResponse;
import com.oya.kr.chat.service.ChatService;

import lombok.RequiredArgsConstructor;

/**
* @author 이상민
* @since 2024.02.27
*/
@RequiredArgsConstructor
@Controller
@RequestMapping("/chat")
public class ChatRoomController {

private final ChatService chatService;

/**
* 관리자 채팅방 리스트 보여주기
*
* @author 이상민
* @since 2024.02.28
*/
@GetMapping("/rooms/admin")
public String adminShowChatRooms(Model model) {
model.addAttribute("chatRoomResponses", chatService.findAllRoom());
return "chat/roomList";
}

/**
* 채팅방 리스트 보여주기
*
* @author 이상민
* @since 2024.02.27
*/
@GetMapping("/rooms")
public String showChatRooms(Model model) {
model.addAttribute("chatRoomResponses", chatService.findAllRoom("test1233@gmail.com"));
return "chat/roomList";
}

/**
* 채팅방 입장하기
*
* @author 이상민
* @since 2024.02.27
*/
@GetMapping("/room/{roomId}")
public String showChatRoomDetails(@PathVariable Long roomId, Model model) {
ChatRoomAndMessageResponse chatRoomResponse = chatService.findRoomById(roomId);
model.addAttribute("chatRoomDetailResponse", chatRoomResponse.getChatRoomDetailResponse());
model.addAttribute("chatMessage", chatRoomResponse.getChatMessageDetailResponse());
return "chat/roomDetails";
}

/**
* 채팅방 생성하기
*
* @author 이상민
* @since 2024.02.27
*/
@PostMapping("/createRoom")
public String createChatRoom(@RequestParam String roomName) {
chatService.createChatRoom(roomName, "test1233@gmail.com");
return "redirect:/chat/rooms";
}
}
40 changes: 40 additions & 0 deletions src/main/java/com/oya/kr/chat/controller/WebSocketController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.oya.kr.chat.controller;

import java.util.List;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;

import com.oya.kr.chat.controller.dto.ChatMessageRequest;
import com.oya.kr.chat.service.ChatService;

import lombok.RequiredArgsConstructor;

@Controller
@RequiredArgsConstructor
public class WebSocketController {

private final ChatService chatService;
private final SimpMessagingTemplate messagingTemplate;

@MessageMapping("/sendMessage")
@SendTo("/topic/messages")
public ChatMessageRequest sendMessage(ChatMessageRequest chatMessageRequest) {
// 메시지를 채팅방에 저장
chatService.saveMessage(chatMessageRequest);

// 이전 메시지를 클라이언트로 전송
List<ChatMessageRequest> previousMessages = chatService.findByChatRoomId(chatMessageRequest.getRoomId());
for (ChatMessageRequest previousMessage : previousMessages) {
messagingTemplate.convertAndSendToUser(
chatMessageRequest.getSender(),
"/topic/messages",
previousMessage
);
}

return chatMessageRequest;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.oya.kr.chat.controller.dto;

import com.oya.kr.chat.controller.dto.response.ChatMessageDetailResponse;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor
@Builder
public class ChatMessageRequest {

private Long roomId;
private String sender;
private String message;
private String sendingTime;

public ChatMessageRequest(ChatMessageDetailResponse detail) {
this.roomId = 1L;
this.sender = null;
this.message = detail.getMessage();
this.sendingTime = detail.getSendingTime();
}

// //메시지 타입 : 입장 채팅
// public enum MessageType{
// ENTER, TALK, JOIN
// }
// private MessageType type; //메시지 타입
// private String roomId;// 방 번호
// private String sender;//채팅을 보낸 사람
// private String message;// 메세지
}
22 changes: 22 additions & 0 deletions src/main/java/com/oya/kr/chat/controller/dto/ChatRoomResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.oya.kr.chat.controller.dto;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class ChatRoomResponse {
private String id;
private String name;
private List<ChatMessageRequest> messages;

public ChatRoomResponse(String name) {
this.id = UUID.randomUUID().toString();
this.name = name;
this.messages = new ArrayList<>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.oya.kr.chat.controller.dto.response;

import com.oya.kr.chat.mapper.dto.response.ChatRoomDetailMapperResponse;
import com.oya.kr.chat.mapper.dto.response.MessageDetailMapperResponse;
import com.oya.kr.global.domain.DateConvertor;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class ChatMessageDetailResponse {

private final String senderNickname;
private final String message;
private final String sendingTime;

public ChatMessageDetailResponse(MessageDetailMapperResponse message) {
this.senderNickname = null;
this.message = message.getContent();
this.sendingTime = DateConvertor.convertDateFormatForResponse(message.getModifiedDate());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.oya.kr.chat.controller.dto.response;

import java.util.List;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class ChatRoomAndMessageResponse {

private final ChatRoomDetailResponse chatRoomDetailResponse;
private final List<ChatMessageDetailResponse> chatMessageDetailResponse;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.oya.kr.chat.controller.dto.response;

import com.oya.kr.chat.mapper.dto.response.ChatRoomDetailMapperResponse;
import com.oya.kr.global.domain.DateConvertor;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class ChatRoomDetailResponse {

private final long chatRoomId;
private final String name;
private final String createdDate;
private final String modifiedDate;

// private final User sender;
// private final User receiver;

public ChatRoomDetailResponse(ChatRoomDetailMapperResponse response) {
this.chatRoomId = response.getId();
this.name = response.getName();
this.createdDate = DateConvertor.convertDateFormatForResponse(response.getCreatedDate());
this.modifiedDate = DateConvertor.convertDateFormatForResponse(response.getModifiedDate());
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/oya/kr/chat/domain/ChatMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.oya.kr.chat.domain;

import org.springframework.stereotype.Component;

import com.oya.kr.global.domain.Base;
import com.oya.kr.user.domain.User;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Component
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ChatMessage extends Base {

private Long id;
private String content;
private ChatRoom chatRoom;
private User sender;
}
20 changes: 20 additions & 0 deletions src/main/java/com/oya/kr/chat/domain/ChatRoom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.oya.kr.chat.domain;

import org.springframework.stereotype.Component;

import com.oya.kr.global.domain.Base;
import com.oya.kr.user.domain.User;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Component
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ChatRoom extends Base {

private Long id;
private String name;
private User creator;
}
12 changes: 12 additions & 0 deletions src/main/java/com/oya/kr/chat/mapper/ChatMessageMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.oya.kr.chat.mapper;

import java.util.List;

import com.oya.kr.chat.mapper.dto.request.CreateMessageMapperRequest;
import com.oya.kr.chat.mapper.dto.response.MessageDetailMapperResponse;

public interface ChatMessageMapper {
void save(CreateMessageMapperRequest createMessageMapperRequest);

List<MessageDetailMapperResponse> findByChatRoomId(Long roomId);
}
13 changes: 13 additions & 0 deletions src/main/java/com/oya/kr/chat/mapper/ChatRoomMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.oya.kr.chat.mapper;

import java.util.List;

import com.oya.kr.chat.mapper.dto.request.CreateChatRoomMapperRequest;
import com.oya.kr.chat.mapper.dto.response.ChatRoomDetailMapperResponse;

public interface ChatRoomMapper {
void save(CreateChatRoomMapperRequest createChatRoomMapperRequest);
List<ChatRoomDetailMapperResponse> findByAll();
List<ChatRoomDetailMapperResponse> findRoomByUser(Long userId);
ChatRoomDetailMapperResponse findRoomById(Long roomId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.oya.kr.chat.mapper.dto.request;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class CreateChatRoomMapperRequest {

private final String name; // 채팅 방 이름
private final Long sender; // creator
}
Loading

0 comments on commit 3e5dfd0

Please sign in to comment.