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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.back.koreaTravelGuide.domain.userChat.chatmessage.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.domain.userChat.chatmessage.service.ChatMessageService
import org.springframework.http.ResponseEntity
import org.springframework.messaging.simp.SimpMessagingTemplate
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.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/api/userchat/rooms")
class ChatMessageController(
private val msgSvc: ChatMessageService,
private val messagingTemplate: SimpMessagingTemplate,
) {
@GetMapping("/{roomId}/messages")
fun listMessages(
@PathVariable roomId: Long,
@RequestParam(required = false) after: Long?,
@RequestParam(defaultValue = "50") limit: Int,
): ResponseEntity<ApiResponse<Any>> {
val messages =
if (after == null) {
msgSvc.getlistbefore(roomId, limit)
} else {
msgSvc.getlistafter(roomId, after)
}
return ResponseEntity.ok(ApiResponse(msg = "메시지 조회", data = messages))
}

@PostMapping("/{roomId}/messages")
fun sendMessage(
@PathVariable roomId: Long,
@RequestBody req: ChatMessageService.SendMessageReq,
): ResponseEntity<ApiResponse<Any>> {
val saved = msgSvc.send(roomId, req)
messagingTemplate.convertAndSend(
"/topic/userchat/$roomId",
ApiResponse(msg = "메시지 전송", data = saved),
)
return ResponseEntity.status(201).body(ApiResponse(msg = "메시지 전송", data = saved))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.back.koreaTravelGuide.domain.userChat.chatmessage.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.domain.userChat.chatmessage.service.ChatMessageService
import org.springframework.messaging.handler.annotation.DestinationVariable
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.handler.annotation.Payload
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.stereotype.Controller

@Controller
class ChatMessageSocketController(
private val chatMessageService: ChatMessageService,
private val messagingTemplate: SimpMessagingTemplate,
) {
@MessageMapping("/userchat/{roomId}/messages")
fun handleMessage(
@DestinationVariable roomId: Long,
@Payload req: ChatMessageService.SendMessageReq,
) {
val saved = chatMessageService.send(roomId, req)
messagingTemplate.convertAndSend(
"/topic/userchat/$roomId",
ApiResponse(msg = "메시지 전송", data = saved),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
package com.back.koreaTravelGuide.domain.userChat.chatroom.controller

import com.back.koreaTravelGuide.common.ApiResponse
import com.back.koreaTravelGuide.domain.userChat.UserChatSseEvents
import com.back.koreaTravelGuide.domain.userChat.chatmessage.service.ChatMessageService
import com.back.koreaTravelGuide.domain.userChat.chatroom.service.ChatRoomService
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.DeleteMapping
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.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter

// 컨트롤러는 임시로 강사님 스타일 따라서 통합해놓았음. 추후 리팩토링 예정
@RestController
@RequestMapping("/api/userchat/rooms")
class ChatRoomController(
private val roomSvc: ChatRoomService,
private val msgSvc: ChatMessageService,
private val events: UserChatSseEvents,
) {
data class StartChatReq(val guideId: Long, val userId: Long)

data class DeleteChatReq(val userId: Long)

// MVP: 같은 페어는 방 재사용
// 같은 페어는 방 재사용
@PostMapping("/start")
fun startChat(
@RequestBody req: StartChatReq,
Expand All @@ -50,36 +42,4 @@ class ChatRoomController(
fun get(
@PathVariable roomId: Long,
) = ResponseEntity.ok(ApiResponse(msg = "채팅방 조회", data = roomSvc.get(roomId)))

@GetMapping("/{roomId}/messages")
fun listMessages(
@PathVariable roomId: Long,
@RequestParam(required = false) after: Long?,
@RequestParam(defaultValue = "50") limit: Int,
): ResponseEntity<ApiResponse<Any>> {
val messages =
if (after == null) {
msgSvc.getlistbefore(roomId, limit)
} else {
msgSvc.getlistafter(roomId, after)
}
return ResponseEntity.ok(ApiResponse(msg = "메시지 조회", data = messages))
}

@PostMapping("/{roomId}/messages")
fun sendMessage(
@PathVariable roomId: Long,
@RequestBody req: ChatMessageService.SendMessageReq,
): ResponseEntity<ApiResponse<Any>> {
val saved = msgSvc.send(roomId, req)
events.publishNew(roomId, saved.id!!)
return ResponseEntity.status(201).body(ApiResponse(msg = "메시지 전송", data = saved))
}

// SSE는 스트림이여서 ApiResponse로 감싸지 않았음
// WebSocket,Stomp 적용되면 바로 삭제 예정
@GetMapping("/{roomId}/events", produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun subscribe(
@PathVariable roomId: Long,
): SseEmitter = events.subscribe(roomId)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.back.koreaTravelGuide.domain.userChat.chatroom.service

import com.back.koreaTravelGuide.domain.userChat.chatmessage.repository.ChatMessageRepository
import com.back.koreaTravelGuide.domain.userChat.chatroom.entity.ChatRoom
import com.back.koreaTravelGuide.domain.userChat.chatroom.repository.ChatRoomRepository
import org.springframework.stereotype.Service
Expand All @@ -9,9 +10,8 @@ import java.time.Instant
@Service
class ChatRoomService(
private val roomRepository: ChatRoomRepository,
private val messageRepository: ChatMessageRepository,
) {
data class CreateRoomReq(val title: String, val guideId: Long, val userId: Long)

@Transactional
fun exceptOneToOneRoom(
guideId: Long,
Expand All @@ -27,7 +27,9 @@ class ChatRoomService(
)
}

fun get(roomId: Long): ChatRoom = roomRepository.findById(roomId).orElseThrow { NoSuchElementException("room not found: $roomId") }
fun get(roomId: Long): ChatRoom =
roomRepository.findById(roomId)
.orElseThrow { NoSuchElementException("room not found: $roomId") }

@Transactional
fun deleteByOwner(
Expand All @@ -39,6 +41,7 @@ class ChatRoomService(
// 예외처리 임시
throw IllegalArgumentException("채팅방 생성자만 삭제할 수 있습니다.")
}
messageRepository.deleteByRoomId(roomId)
roomRepository.deleteById(roomId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.back.koreaTravelGuide.domain.userChat.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

// userChat에서만 사용할 것 같아서 전역에 두지 않고 userChat 도메인에 두었음

@Configuration
@EnableWebSocketMessageBroker
class UserChatWebSocketConfig : WebSocketMessageBrokerConfigurer {
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
registry.addEndpoint("/ws/userchat")
.setAllowedOriginPatterns("*")
.withSockJS()
}

override fun configureMessageBroker(registry: MessageBrokerRegistry) {
registry.enableSimpleBroker("/topic")
registry.setApplicationDestinationPrefixes("/pub")
}
}