diff --git a/build.gradle b/build.gradle index 6505e07..17a8a2b 100755 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,8 @@ dependencies { // graphQL 클래스, 인터페이스를 제공하는 라이브러리 implementation 'com.graphql-java-kickstart:graphql-spring-boot-starter:11.0.0' - runtimeOnly 'com.graphql-java-kickstart:graphiql-spring-boot-starter:11.0.0' + implementation 'org.projectlombok:lombok:1.18.26' + runtimeOnly 'com.graphql-java-kickstart:graphiql-spring-boot-starter:11.0.0' // graphQL 쿼리 요청에 사용되는 라이브러리 implementation 'com.graphql-java-kickstart:playground-spring-boot-starter:11.0.0' diff --git a/src/main/java/com/example/ai_jeju/config/WebConfig.java b/src/main/java/com/example/ai_jeju/config/WebConfig.java index 02a3dfe..845f243 100644 --- a/src/main/java/com/example/ai_jeju/config/WebConfig.java +++ b/src/main/java/com/example/ai_jeju/config/WebConfig.java @@ -13,7 +13,6 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { - // 모든 경로에 대해 인터셉터를 적용 (필요에 따라 경로를 지정할 수 있음) registry.addInterceptor(headerCheckInterceptor).addPathPatterns("/**"); } } diff --git a/src/main/java/com/example/ai_jeju/controller/ChatController.java b/src/main/java/com/example/ai_jeju/controller/ChatController.java index d0f7aa8..5083046 100644 --- a/src/main/java/com/example/ai_jeju/controller/ChatController.java +++ b/src/main/java/com/example/ai_jeju/controller/ChatController.java @@ -46,12 +46,16 @@ public void message(ChatMessageDto messageDto, @Header("simpSessionAttributes") try { String nickname = (String) sessionAttributes.get("nickname"); + String profileImg = (String) sessionAttributes.get("profileImg"); log.info("Received message: " + messageDto.toString()); // sender가 null일 경우 세션에서 추출한 nickname을 sender로 설정 if (messageDto.getSender() == null) { messageDto.setSender(nickname); } + if (messageDto.getProfileImg() == null) { + messageDto.setProfileImg(profileImg); + } switch (messageDto.getType()) { case ENTER: @@ -64,14 +68,28 @@ public void message(ChatMessageDto messageDto, @Header("simpSessionAttributes") break; } - ChatMessage chatMessage = ChatMessage.builder() - .roomId(messageDto.getRoomId()) - .sender(messageDto.getSender()) // nickname이 sender로 설정됨 - .message(messageDto.getMessage()) - .timestamp(LocalDateTime.now()) - .type(messageDto.getType().name()) - .build(); - chatMessageRepository.save(chatMessage); + // roomId를 사용해 ChatRoom 객체를 가져오기 + ChatRoom chatRoom = chatRoomRepository.findByRoomId(messageDto.getRoomId()) + .orElseThrow(() -> new IllegalArgumentException("Invalid roomId: " + messageDto.getRoomId())); + + // ENTER 타입이 아닌 경우에만 메시지를 저장하기 + if (messageDto.getType() != ChatMessageDto.MessageType.ENTER) { + try { + ChatMessage chatMessage = ChatMessage.builder() + .chatRoom(chatRoom) + .sender(messageDto.getSender()) + .message(messageDto.getMessage()) + .profileImg(messageDto.getProfileImg()) + .timestamp(LocalDateTime.now()) + .type(messageDto.getType().name()) + .build(); + log.info("Saving ChatMessage: " + chatMessage.toString()); + chatMessageRepository.save(chatMessage); + } catch (Exception e) { + log.error("Error saving ChatMessage", e); + } + } + log.info("Sending message to /sub/chat/room/" + messageDto.getRoomId() + ": " + messageDto.toString()); messagingTemplate.convertAndSend("/sub/chat/room/" + messageDto.getRoomId(), messageDto); @@ -81,26 +99,48 @@ public void message(ChatMessageDto messageDto, @Header("simpSessionAttributes") } - //@GetMapping("/chatroom") - //public String chat(@RequestParam("roomId") String roomId, Model model) { - // model.addAttribute("roomId", roomId); - // return "chat"; // chat.html 파일을 반환 - //} + @GetMapping("/chatroom") + public String chat(@RequestParam("roomId") String roomId, Model model) { + model.addAttribute("roomId", roomId); + return "chat"; // chat.html 파일을 반환 + } @GetMapping("/chat/previous") @ResponseBody public List getPreviousMessages( @RequestParam("roomId") String roomId, @RequestParam(value = "lastMessageid", required = false) Optional lastMessageId) { - return chatService.previousMessages(roomId, lastMessageId.orElse(null)); + + // roomId를 사용해 ChatRoom 객체 가져오기 + ChatRoom chatRoom = chatRoomRepository.findByRoomId(roomId) + .orElseThrow(() -> new IllegalArgumentException("Invalid roomId: " + roomId)); + + return chatService.previousMessages(chatRoom, lastMessageId.orElse(null)); } @GetMapping("/chat/allprevious") @ResponseBody public List getAllMessages(@RequestParam("roomId") String roomId) { - return chatService.getAllMessages(roomId); + + // roomId를 사용해 ChatRoom 객체를 가져오기 + ChatRoom chatRoom = chatRoomRepository.findByRoomId(roomId) + .orElseThrow(() -> new IllegalArgumentException("Invalid roomId: " + roomId)); + + return chatService.getAllMessages(chatRoom); } + @GetMapping("/chat/messagecount") + @ResponseBody + public int getMessageCount(@RequestParam("roomId") String roomId) { + + + ChatRoom chatRoom = chatRoomRepository.findByRoomId(roomId) + .orElseThrow(() -> new IllegalArgumentException("Invalid roomId: " + roomId)); + + return chatService.getMessageCount(chatRoom); + } + + diff --git a/src/main/java/com/example/ai_jeju/controller/ChatRoomController.java b/src/main/java/com/example/ai_jeju/controller/ChatRoomController.java index 5e3c599..e045f0f 100644 --- a/src/main/java/com/example/ai_jeju/controller/ChatRoomController.java +++ b/src/main/java/com/example/ai_jeju/controller/ChatRoomController.java @@ -1,12 +1,17 @@ package com.example.ai_jeju.controller; +import com.example.ai_jeju.domain.ChatMessage; import com.example.ai_jeju.domain.ChatRoom; +import com.example.ai_jeju.handler.StompHandler; import com.example.ai_jeju.service.ChatService; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @RequiredArgsConstructor @RestController @@ -14,6 +19,7 @@ public class ChatRoomController { private final ChatService chatService; + private final StompHandler stompHandler; @GetMapping("/rooms") public List room() { @@ -34,4 +40,25 @@ public String chatRooms() { return "chatrooms"; } } -} + + @GetMapping("/room/{roomId}/lastmessage") + public ChatMessage getLastMessage(@PathVariable("roomId") String roomId) { + ChatRoom chatRoom = chatService.findRoomById(roomId); + if (chatRoom == null) { + throw new IllegalArgumentException("Invalid roomId: " + roomId); + } + return chatService.findLastMessage(chatRoom); + } + + + @GetMapping("/users/{roomId}/count") + public int getUserCount(@PathVariable("roomId") String roomId) { + return stompHandler.getUserCount(roomId); + } + + + + + + +} \ No newline at end of file diff --git a/src/main/java/com/example/ai_jeju/controller/UserController.java b/src/main/java/com/example/ai_jeju/controller/UserController.java index ae9b7d0..4b67745 100755 --- a/src/main/java/com/example/ai_jeju/controller/UserController.java +++ b/src/main/java/com/example/ai_jeju/controller/UserController.java @@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.*; import java.io.IOException; +import java.util.Map; @RestController @RequestMapping("/api/users") @@ -29,10 +30,11 @@ public Long registerUser(@RequestBody SignUpRequest signUpRequest, HttpServletRe } @GetMapping("/checks") - public Long CheckIfUser(@RequestParam(name = "email") String email, HttpServletRequest request, HttpServletResponse response){ - return userService.checkIfUser(email,request,response); + public Map CheckIfUser(@RequestParam(name = "email") String email, HttpServletRequest request, HttpServletResponse response){ + return userService.checkIfUser(email, request, response); } + //탈퇴하기 @GetMapping("/withdraw") public ResponseEntity signOut(@RequestBody WithdrawRequest withdrawRequest) { diff --git a/src/main/java/com/example/ai_jeju/domain/ChatMessage.java b/src/main/java/com/example/ai_jeju/domain/ChatMessage.java index 58b75aa..9689688 100644 --- a/src/main/java/com/example/ai_jeju/domain/ChatMessage.java +++ b/src/main/java/com/example/ai_jeju/domain/ChatMessage.java @@ -1,13 +1,11 @@ package com.example.ai_jeju.domain; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.annotations.UpdateTimestamp; import java.time.LocalDateTime; @@ -22,9 +20,15 @@ public class ChatMessage { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String roomId; + @ManyToOne + @JoinColumn(name = "room_id", referencedColumnName = "roomId") + private ChatRoom chatRoom; + private String sender; private String message; private String type; + @UpdateTimestamp + @Column(name = "timestamp") private LocalDateTime timestamp; + private String profileImg; } \ No newline at end of file diff --git a/src/main/java/com/example/ai_jeju/domain/ChatRoom.java b/src/main/java/com/example/ai_jeju/domain/ChatRoom.java index fd3b3e3..3b43b88 100644 --- a/src/main/java/com/example/ai_jeju/domain/ChatRoom.java +++ b/src/main/java/com/example/ai_jeju/domain/ChatRoom.java @@ -1,9 +1,6 @@ package com.example.ai_jeju.domain; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; +import jakarta.persistence.*; import lombok.Data; @Data @@ -11,23 +8,25 @@ public class ChatRoom { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - private String roomId; + private String name; + private String description; + private String imgurl; // 기본 생성자 public ChatRoom() { } // 이름과 roomId를 인자로 받는 생성자 - public ChatRoom(String roomId, String name) { + public ChatRoom(String roomId, String name, String description, String imgurl) { this.roomId = roomId; this.name = name; + this.description = description; + this.imgurl = imgurl; } - public static ChatRoom create(String roomId, String name) { - return new ChatRoom(roomId, name); + public static ChatRoom create(String roomId, String name, String description, String imgurl) { + return new ChatRoom(roomId, name, description, imgurl); } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/ai_jeju/domain/Emergency.java b/src/main/java/com/example/ai_jeju/domain/Emergency.java index 7bc6050..da89b69 100644 --- a/src/main/java/com/example/ai_jeju/domain/Emergency.java +++ b/src/main/java/com/example/ai_jeju/domain/Emergency.java @@ -24,6 +24,8 @@ public class Emergency { private String imgsrc; @Column(length = 1024) private String operationtime; + @Column(length = 1024) + private String breaktime; private String category; double mapx; double mapy; diff --git a/src/main/java/com/example/ai_jeju/domain/Store.java b/src/main/java/com/example/ai_jeju/domain/Store.java index 193d407..3d45a8a 100644 --- a/src/main/java/com/example/ai_jeju/domain/Store.java +++ b/src/main/java/com/example/ai_jeju/domain/Store.java @@ -21,7 +21,7 @@ public class Store { String name; //이미지 소스 - @Column(name = "imgSrc",updatable = false,nullable = true) + @Column(name = "imgSrc",updatable = false,nullable = true, columnDefinition = "TEXT") String imgSrc; @Column(name = "address",updatable = false,nullable = true) @@ -46,26 +46,26 @@ public class Store { //유모차 대여여부 @Column(name = "stroller",updatable = false,nullable = true) - boolean stroller; + Boolean stroller; //유모차 편의성 @Column(name = "strollerVal",updatable = false,nullable = true) - boolean strollerVal; + Boolean strollerVal; //아이 스페어 체어 @Column(name = "babySpareChair",updatable = false,nullable = true) - boolean babySpareChair; + Boolean babySpareChair; //아이 놀이방 @Column(name = "playground",updatable = false,nullable = true) - boolean playground; + Boolean playground; //노키즈존 여부 @Column(name = "noKidsZone",updatable = false,nullable = true) - boolean noKidsZone; + Boolean noKidsZone; @Column(name = "categoryId",updatable = false,nullable = true) - int categoryId; + Integer categoryId; @Column(name = "operationTime",updatable = false,nullable = true) String operationTime; diff --git a/src/main/java/com/example/ai_jeju/dto/ChatMessageDto.java b/src/main/java/com/example/ai_jeju/dto/ChatMessageDto.java index 31d1511..613756f 100644 --- a/src/main/java/com/example/ai_jeju/dto/ChatMessageDto.java +++ b/src/main/java/com/example/ai_jeju/dto/ChatMessageDto.java @@ -10,11 +10,12 @@ public class ChatMessageDto { public enum MessageType { - ENTER, TALK, EXIT; + TALK, EXIT, ENTER; } private MessageType type; private String roomId; private String sender; private String message; + private String profileImg; } \ No newline at end of file diff --git a/src/main/java/com/example/ai_jeju/handler/StompHandler.java b/src/main/java/com/example/ai_jeju/handler/StompHandler.java index c58e43b..d92d775 100644 --- a/src/main/java/com/example/ai_jeju/handler/StompHandler.java +++ b/src/main/java/com/example/ai_jeju/handler/StompHandler.java @@ -1,6 +1,5 @@ package com.example.ai_jeju.handler; -import com.example.ai_jeju.domain.User; import com.example.ai_jeju.jwt.TokenProvider; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -10,6 +9,12 @@ import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.stereotype.Component; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.Map; @RequiredArgsConstructor @Component @@ -18,39 +23,141 @@ public class StompHandler implements ChannelInterceptor { private final TokenProvider tokenProvider; private static final String BEARER_PREFIX = "Bearer "; + private final ConcurrentMap roomUserCount = new ConcurrentHashMap<>(); + private final ConcurrentMap> userRoomEntryCount = new ConcurrentHashMap<>(); @Override public Message preSend(Message message, MessageChannel channel) { log.info("preSend method called"); StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); - if (StompCommand.CONNECT == accessor.getCommand()) { // WebSocket 연결 요청 + // WebSocket 연결 요청 처리 + if (StompCommand.CONNECT == accessor.getCommand()) { String jwtToken = accessor.getFirstNativeHeader("Authorization"); - if (jwtToken == null) { - log.error("Authorization header is missing"); + if (jwtToken == null || !jwtToken.startsWith(BEARER_PREFIX)) { + log.error("Authorization header is missing or does not start with 'Bearer '"); + throw new IllegalArgumentException("Invalid or missing Authorization header"); + } + + String token = jwtToken.substring(BEARER_PREFIX.length()); + log.info("Extracted token: {}", token); + + if (token.isEmpty()) { + log.error("JWT token is empty"); + throw new IllegalArgumentException("JWT token is empty"); + } + + boolean isValid = tokenProvider.validToken(token); + if (isValid) { + log.info("JWT Token is valid. Proceeding with connection."); + + // 토큰에서 nickname 추출 + String nickname = tokenProvider.extractNickname(token); + + String profileImg = tokenProvider.extractProfileImg(token); + log.info("Extracted nickname: {}", nickname); + + // WebSocket 세션에 nickname 저장 + accessor.getSessionAttributes().put("nickname", nickname); + accessor.getSessionAttributes().put("profileImg", profileImg); + accessor.getSessionAttributes().put("connected", true); // 연결 상태 저장 + accessor.getSessionAttributes().put("enter", false); // 초기에는 false로 설정 + + } else { - log.info("Authorization header present: {}", jwtToken); - String token = jwtToken.substring(7); - log.info("Extracted token: {}", token); - - boolean isValid = tokenProvider.validToken(token); - if (isValid) { - log.info("JWT Token is valid. Proceeding with connection."); - - // 토큰에서 nickname 추출 - String nickname = tokenProvider.extractNickname(token); - log.info("Extracted nickname: {}", nickname); - - // WebSocket 세션에 nickname 저장 - accessor.getSessionAttributes().put("nickname", nickname); - } else { - log.error("Invalid JWT Token"); - throw new IllegalArgumentException("Invalid JWT Token provided"); + log.error("Invalid JWT Token"); + throw new IllegalArgumentException("Invalid JWT Token provided"); + } + } + + // 메시지 전송 요청 처리 + else if (StompCommand.SEND == accessor.getCommand()) { + String destination = accessor.getDestination(); + + // 메시지의 목적지가 "/pub/chat/message"인지 확인 + if ("/pub/chat/message".equals(destination)) { + String messageBody = new String((byte[]) message.getPayload()); + log.info("Message body: {}", messageBody); + + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(messageBody); + + String roomId = jsonNode.get("roomId").asText(); + String messageType = jsonNode.get("type").asText(); + + // 토큰에서 가져온 nickname을 sender로 사용 + String sender = (String) accessor.getSessionAttributes().get("nickname"); + log.info("Sender retrieved from session: {}", sender); + + if ("ENTER".equals(messageType)) { + log.info("User '{}' has entered room '{}'", sender, roomId); + + // 사용자가 방에 입장할 때마다 방의 사용자 수 증가 + roomUserCount.merge(roomId, 1, Integer::sum); + log.info("Room '{}' user count: {}", roomId, roomUserCount.get(roomId)); + + // 사용자 방 입장 횟수 증가 + userRoomEntryCount + .computeIfAbsent(sender, k -> new ConcurrentHashMap<>()) + .merge(roomId, 1, Integer::sum); + log.info("User '{}' entry count for room '{}': {}", sender, roomId, userRoomEntryCount.get(sender).get(roomId)); + + // 사용자가 실제로 ENTER 했음을 표시 + accessor.getSessionAttributes().put("enter", true); + + accessor.getSessionAttributes().put("roomId", roomId); + } + + // 메시지 전송 시 sender를 설정 + if ("TALK".equals(messageType)) { + log.info("User '{}' sent message to room '{}': {}", sender, roomId, jsonNode.get("message").asText()); + // 메시지에 sender 추가하여 브로드캐스트 + // messagingTemplate.convertAndSend("/sub/chat/room/" + roomId, updatedMessage); + } + + } catch (Exception e) { + log.error("Error parsing message body", e); + } + } + } + + else if (StompCommand.DISCONNECT == accessor.getCommand()) { + String sessionId = accessor.getSessionId(); + log.info("DISCONNECT command received for session: {}", sessionId); + + Boolean connected = (Boolean) accessor.getSessionAttributes().get("connected"); + Boolean entered = (Boolean) accessor.getSessionAttributes().get("enter"); + + if (connected != null && connected && entered != null && entered) { + String nickname = (String) accessor.getSessionAttributes().get("nickname"); + String roomId = (String) accessor.getSessionAttributes().get("roomId"); // 세션에서 roomId를 가져옴 + + if (nickname != null && roomId != null) { + Integer count = userRoomEntryCount.getOrDefault(nickname, new ConcurrentHashMap<>()).get(roomId); + if (count != null && count > 0) { + roomUserCount.merge(roomId, -1, Integer::sum); + userRoomEntryCount.get(nickname).merge(roomId, -1, Integer::sum); + log.info("User '{}' has left room '{}'. Updated user count: {}", nickname, roomId, roomUserCount.get(roomId)); + + // 마지막 입장인 경우 방 목록에서 제거 + if (userRoomEntryCount.get(nickname).get(roomId) == 0) { + userRoomEntryCount.get(nickname).remove(roomId); + } + } } + + accessor.getSessionAttributes().put("connected", false); + } else { + log.warn("DISCONNECT called but user was not marked as connected or had not entered."); } } return message; } + + public int getUserCount(String roomId) { + return roomUserCount.getOrDefault(roomId, 0); + } } diff --git a/src/main/java/com/example/ai_jeju/jwt/TokenProvider.java b/src/main/java/com/example/ai_jeju/jwt/TokenProvider.java index 710bb85..146926c 100644 --- a/src/main/java/com/example/ai_jeju/jwt/TokenProvider.java +++ b/src/main/java/com/example/ai_jeju/jwt/TokenProvider.java @@ -44,6 +44,7 @@ private String makeToken(Date expiry, User user) { .setSubject(user.getEmail()) .claim("id", user.getId()) .claim("nickname", user.getNickname()) + .claim("profileImg", user.getProfileImg()) .signWith(key, SignatureAlgorithm.HS512) // 동일한 키와 알고리즘 사용 .compact(); } @@ -81,6 +82,11 @@ public String extractNickname(String token) { return claims.get("nickname", String.class); } + public String extractProfileImg(String token) { + Claims claims = getClaims(token); + return claims.get("profileImg", String.class); + } + private Claims getClaims(String token) { return Jwts.parser() .setSigningKey(key) diff --git a/src/main/java/com/example/ai_jeju/repository/ChatMessageRepository.java b/src/main/java/com/example/ai_jeju/repository/ChatMessageRepository.java index f23e8a0..371ee1a 100644 --- a/src/main/java/com/example/ai_jeju/repository/ChatMessageRepository.java +++ b/src/main/java/com/example/ai_jeju/repository/ChatMessageRepository.java @@ -1,16 +1,25 @@ package com.example.ai_jeju.repository; import com.example.ai_jeju.domain.ChatMessage; +import com.example.ai_jeju.domain.ChatRoom; import org.apache.logging.log4j.message.Message; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @Repository public interface ChatMessageRepository extends JpaRepository { - List findByRoomIdOrderByIdAsc(String roomId); - List findTop10ByRoomIdOrderByIdDesc(String roomId); - List findTop10ByRoomIdAndIdLessThanOrderByIdDesc(String roomId, Long id); + // ChatRoom 객체를 기반으로 메시지를 가져옵니다. + List findByChatRoomOrderByIdAsc(ChatRoom chatRoom); + + List findTop10ByChatRoomOrderByIdDesc(ChatRoom chatRoom); + + List findTop10ByChatRoomAndIdLessThanOrderByIdDesc(ChatRoom chatRoom, Long id); + + Optional findTop1ByChatRoomOrderByIdDesc(ChatRoom chatRoom); + + int countByChatRoom(ChatRoom chatRoom); } \ No newline at end of file diff --git a/src/main/java/com/example/ai_jeju/repository/ChatRoomRepository.java b/src/main/java/com/example/ai_jeju/repository/ChatRoomRepository.java index 5bab7ab..8972938 100644 --- a/src/main/java/com/example/ai_jeju/repository/ChatRoomRepository.java +++ b/src/main/java/com/example/ai_jeju/repository/ChatRoomRepository.java @@ -7,6 +7,6 @@ import java.util.Optional; @Repository -public interface ChatRoomRepository extends JpaRepository { +public interface ChatRoomRepository extends JpaRepository { Optional findByRoomId(String roomId); -} +} \ No newline at end of file diff --git a/src/main/java/com/example/ai_jeju/service/ChatService.java b/src/main/java/com/example/ai_jeju/service/ChatService.java index 43763bc..923e10f 100644 --- a/src/main/java/com/example/ai_jeju/service/ChatService.java +++ b/src/main/java/com/example/ai_jeju/service/ChatService.java @@ -15,20 +15,16 @@ @RequiredArgsConstructor public class ChatService { - @Autowired - private ChatMessageRepository chatMessageRepository; - + private final ChatMessageRepository chatMessageRepository; private final ChatRoomRepository chatRoomRepository; @PostConstruct public void init() { - // 데이터베이스에 이미 채팅방이 존재하는지 확인 if (chatRoomRepository.count() == 0) { - // 방 3개를 고정적으로 생성하여 데이터베이스에 저장 - chatRoomRepository.save(new ChatRoom("1", "Room 1")); - chatRoomRepository.save(new ChatRoom("2", "Room 2")); - chatRoomRepository.save(new ChatRoom("3", "Room 3")); + chatRoomRepository.save(new ChatRoom("1", "설렘 가득한 여행 준비", "제주 여행 계획을 짜고있는 엄마아빠들과 소통해요", "https://ai-jeju.s3.ap-northeast-2.amazonaws.com/%EC%9D%B4%EB%AF%B8%EC%A7%801.png")); + chatRoomRepository.save(new ChatRoom("2", "즐거운 제주 여행", "제주 여행을 즐기고 있는 엄마아빠들과 소통해요", "https://ai-jeju.s3.ap-northeast-2.amazonaws.com/%EC%9D%B4%EB%AF%B8%EC%A7%802.png")); + chatRoomRepository.save(new ChatRoom("3", "제주에서 새로운 인연", "아이제주를 통해 새로운 인연을 만들어요", "https://ai-jeju.s3.ap-northeast-2.amazonaws.com/%EC%9D%B4%EB%AF%B8%EC%A7%803.jpg")); } } @@ -40,16 +36,26 @@ public ChatRoom findRoomById(String roomId) { return chatRoomRepository.findByRoomId(roomId).orElse(null); } - public List getAllMessages(String roomId) { - return chatMessageRepository.findByRoomIdOrderByIdAsc(roomId); + public List getAllMessages(ChatRoom chatRoom) { + return chatMessageRepository.findByChatRoomOrderByIdAsc(chatRoom); } - public List previousMessages(String roomId, Long lastMessageId) { + public List previousMessages(ChatRoom chatRoom, Long lastMessageId) { if (lastMessageId == null) { // 마지막 메시지 ID가 없으면 해당 채팅방의 최신 메시지 10개 가져오기 - return chatMessageRepository.findTop10ByRoomIdOrderByIdDesc(roomId); + return chatMessageRepository.findTop10ByChatRoomOrderByIdDesc(chatRoom); } // 특정 ID 이전의 해당 채팅방 메시지 10개 가져오기 - return chatMessageRepository.findTop10ByRoomIdAndIdLessThanOrderByIdDesc(roomId, lastMessageId); + return chatMessageRepository.findTop10ByChatRoomAndIdLessThanOrderByIdDesc(chatRoom, lastMessageId); + } + + public ChatMessage findLastMessage(ChatRoom chatRoom) { + return chatMessageRepository.findTop1ByChatRoomOrderByIdDesc(chatRoom).orElse(null); } -} + + public int getMessageCount(ChatRoom chatRoom) { + return chatMessageRepository.countByChatRoom(chatRoom); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/example/ai_jeju/service/UserService.java b/src/main/java/com/example/ai_jeju/service/UserService.java index 0ba82d8..45f3f8e 100755 --- a/src/main/java/com/example/ai_jeju/service/UserService.java +++ b/src/main/java/com/example/ai_jeju/service/UserService.java @@ -27,9 +27,7 @@ import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; import static com.example.ai_jeju.handler.SignUpHandler.ACCESS_TOKEN_COOKIE_NAME; //import static com.example.ai_jeju.handler.SignUpHandler.REFRESH_TOKEN_COOKIE_NAME; @@ -58,20 +56,29 @@ public class UserService { * checkIfUser : 기존 회원여부 확인 * 기존 회원이라면 객체 (아이디만) 반환 , AccessToken 쿠키로 발급 */ - public Long checkIfUser(String email, HttpServletRequest request, HttpServletResponse response){ + public Map checkIfUser(String email, HttpServletRequest request, HttpServletResponse response) { Optional existingUser = userRepository.findByEmail(email); - /*--------------------------------------------------------------------------------------------------*/ + Map result = new HashMap<>(); + if (existingUser.isPresent()) { User user = existingUser.get(); - String accessToken = tokenProvider.generateToken(user,ACCESS_TOKEN_DURATION); - addAccessTokenToCookie(request,response, accessToken); - return user.getId(); - } - /*--------------------------------------------------------------------------------------------------*/ - else{ - return null; + String accessToken = tokenProvider.generateToken(user, ACCESS_TOKEN_DURATION); + + result.put("statusCode", 1000); + result.put("message", "existinguser"); + result.put("data", Map.of( + "userId", user.getId(), + "accessToken", accessToken + )); + } else { + result.put("statusCode", 2000); + result.put("message", "notexistinguser"); + result.put("data", null); } + + return result; } + /** * login/signu up flow-3 * registerUser : 새로운 회원 DB 저장 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1efe566..8eabd73 100755 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,21 +1,21 @@ spring.application.name=ai_jeju -server.port = 7080 +server.port = 5000 spring.jpa.open-in-view=false # MySQL spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # DB Source URL -spring.datasource.url=jdbc:mysql://112.219.81.130:3310/ai_jeju?serverTimezone=UTC +spring.datasource.url=jdbc:mysql://database-1.c5u0os4m64uc.ap-northeast-2.rds.amazonaws.com/shop # DB username -spring.datasource.username=root +spring.datasource.username=shop # DB password -spring.datasource.password=!@Knp2020!@ - +spring.datasource.password=shopsuccess spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE + spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect diff --git a/src/main/resources/templates/chat.html b/src/main/resources/templates/chat.html index 68af15b..6c4d01c 100644 --- a/src/main/resources/templates/chat.html +++ b/src/main/resources/templates/chat.html @@ -27,9 +27,10 @@ width: calc(100% - 60px); padding: 10px; } - .send-button { + .send-button, .leave-button, .back-button { padding: 10px; cursor: pointer; + margin-top: 10px; } @@ -40,20 +41,25 @@

+
diff --git a/src/main/resources/templates/chatrooms.html b/src/main/resources/templates/chatrooms.html index 1e3a1fb..168963b 100644 --- a/src/main/resources/templates/chatrooms.html +++ b/src/main/resources/templates/chatrooms.html @@ -1,10 +1,10 @@ - - - Chat Rooms -
-
- -
+
+ +
+ + + \ No newline at end of file