-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
#71 stomp
- Loading branch information
Showing
8 changed files
with
235 additions
and
71 deletions.
There are no files selected for viewing
80 changes: 80 additions & 0 deletions
80
src/main/java/com/book/backend/domain/message/controller/MessageController.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,80 @@ | ||
package com.book.backend.domain.message.controller; | ||
|
||
import com.book.backend.domain.message.dto.MessageRequestDto; | ||
import com.book.backend.domain.message.dto.MessageResponseDto; | ||
import com.book.backend.domain.message.entity.Message; | ||
import com.book.backend.domain.message.service.MessageService; | ||
import com.book.backend.global.ResponseTemplate; | ||
import com.book.backend.global.log.RequestLogger; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.Parameter; | ||
import io.swagger.v3.oas.annotations.media.Content; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import io.swagger.v3.oas.annotations.parameters.RequestBody; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.domain.Sort; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.messaging.handler.annotation.MessageMapping; | ||
import org.springframework.messaging.simp.SimpMessageSendingOperations; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import java.util.List; | ||
|
||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
@Tag(name="채팅", description = "메세지 저장 / 메세지 불러오기") | ||
public class MessageController { | ||
private final MessageService messageService; | ||
private final ResponseTemplate responseTemplate; | ||
private final SimpMessageSendingOperations sendingOperations; | ||
|
||
// 채팅 저장하기 (apic 으로 테스트) | ||
@MessageMapping("/message") | ||
public void chat(MessageRequestDto messageRequestDto) { | ||
RequestLogger.param(new String[]{"messageRequestDto"}, messageRequestDto); | ||
MessageResponseDto response = messageService.saveMessage(messageRequestDto); | ||
sendingOperations.convertAndSend("/sub/message/" + messageRequestDto.getOpentalkId(), response); // 수신자들에게 전송 | ||
} | ||
|
||
|
||
// 채팅 불러오기 | ||
@Operation(summary="채팅 불러오기 (특정 오픈톡)", description="오픈톡 ID 를 입력으로 받아 pageSize개 데이터를 반환합니다. (pageNo로 페이지네이션)", | ||
parameters = {@Parameter(name = "opentalkId", description = "오픈톡 DB ID"), @Parameter(name = "pageNo", description = "페이지 번호(0부터)"), @Parameter(name = "pageSize", description = "페이지 당 개수")}, | ||
responses = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = MessageResponseDto.class)), | ||
description = MessageResponseDto.description)}) | ||
@GetMapping("/api/message/get") | ||
public ResponseEntity<?> getChat(@RequestParam String opentalkId, int pageNo, int pageSize) { | ||
RequestLogger.param(new String[]{"opentalkId, pageNo, pageSize"}, opentalkId, pageNo, pageSize); | ||
|
||
Pageable pageRequest = PageRequest.of(pageNo, pageSize, Sort.by("createdAt").descending()); | ||
Page<Message> MessagePage = messageService.getMessage(opentalkId, pageRequest); | ||
List<MessageResponseDto> response = messageService.pageToDto(MessagePage); | ||
|
||
return responseTemplate.success(response, HttpStatus.OK); | ||
} | ||
|
||
// swagger docs 에 남기기 위한 용도 | ||
@Operation(summary="채팅 stomp 통신", description="APIC 테스터기를 이용해서 stomp 통신을 합니다. \n" + | ||
"- Request URL: ws://52.79.187.133:8080/ws-stomp \n"+ | ||
"- Destination Queue: /pub/message \n"+ | ||
"- Subscription URL: /sub/message/{opentalkId}", | ||
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = MessageRequestDto.class))), | ||
responses = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = MessageResponseDto.class)), | ||
description = MessageResponseDto.description)}) | ||
@PostMapping("") | ||
public void chatForSwagger(MessageRequestDto messageRequestDto) { | ||
return; | ||
} | ||
} |
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
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
103 changes: 103 additions & 0 deletions
103
src/main/java/com/book/backend/domain/message/service/MessageService.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,103 @@ | ||
package com.book.backend.domain.message.service; | ||
|
||
import com.book.backend.domain.auth.service.CustomUserDetailsService; | ||
import com.book.backend.domain.message.dto.MessageRequestDto; | ||
import com.book.backend.domain.message.dto.MessageResponseDto; | ||
import com.book.backend.domain.message.entity.Message; | ||
import com.book.backend.domain.message.mapper.MessageMapper; | ||
import com.book.backend.domain.message.repository.MessageRepository; | ||
import com.book.backend.domain.opentalk.entity.Opentalk; | ||
import com.book.backend.domain.opentalk.repository.OpentalkRepository; | ||
import com.book.backend.exception.CustomException; | ||
import com.book.backend.exception.ErrorCode; | ||
import com.book.backend.util.JwtUtil; | ||
import io.jsonwebtoken.ExpiredJwtException; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.LinkedList; | ||
import java.util.List; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class MessageService { | ||
private final MessageRepository messageRepository; | ||
private final OpentalkRepository opentalkRepository; | ||
private final MessageMapper messageMapper; | ||
private final JwtUtil jwtUtil; | ||
private final CustomUserDetailsService userDetailsService; | ||
|
||
@Transactional | ||
public MessageResponseDto saveMessage(MessageRequestDto messageRequestDto){ | ||
log.trace("MessageService > saveMessage()"); | ||
// 토큰 유효성 검사 | ||
String token = messageRequestDto.getJwtToken(); | ||
validateToken(token); | ||
|
||
// message DB에 저장 | ||
Message message = messageMapper.convertToMessage(messageRequestDto); | ||
try{ | ||
messageRepository.save(message); | ||
} catch (Exception e){ | ||
throw new CustomException(ErrorCode.MESSAGE_SAVE_FAILED); | ||
} | ||
return messageMapper.convertToMessageResponseDto(message); | ||
} | ||
|
||
|
||
public void validateToken(String token) { | ||
try{ | ||
String username = jwtUtil.getUsernameFromToken(token); // username 가져옴 | ||
// 현재 SecurityContextHolder에 인증객체가 있는지 확인 | ||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { | ||
UserDetails userDetails; | ||
try { | ||
userDetails = userDetailsService.loadUserByloginId(username); | ||
} catch (CustomException e1) { | ||
try { | ||
userDetails = userDetailsService.loadUserByKakaoId(username); | ||
} catch (CustomException e2) { | ||
userDetails = userDetailsService.loadUserByAppleId(username); | ||
} | ||
} | ||
|
||
// 토큰 유효성 검증 | ||
if (jwtUtil.isValidToken(token, userDetails)) { | ||
UsernamePasswordAuthenticationToken authenticated | ||
= new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | ||
SecurityContextHolder.getContext().setAuthentication(authenticated); | ||
} | ||
} | ||
} catch (ExpiredJwtException e) { | ||
throw new CustomException(ErrorCode.JWT_EXPIRED); | ||
} catch (Exception e) { | ||
throw new CustomException(ErrorCode.WRONG_JWT_TOKEN); | ||
} | ||
} | ||
|
||
public Page<Message> getMessage(String opentalkId, Pageable pageRequest){ | ||
log.trace("MessageService > getOpentalkMessage()"); | ||
// 오픈톡 ID로 opentlak 객체 찾기 | ||
Opentalk opentalk = opentalkRepository.findByOpentalkId(Long.parseLong(opentalkId)).orElseThrow(() -> new CustomException(ErrorCode.OPENTALK_NOT_FOUND)); | ||
return messageRepository.findAllByOpentalk(opentalk, pageRequest); | ||
} | ||
|
||
public List<MessageResponseDto> pageToDto(Page<Message> page){ | ||
log.trace("MessageService > pageToDto()"); | ||
List<Message> messages = page.getContent(); | ||
List<MessageResponseDto> messageList = new LinkedList<>(); | ||
|
||
for(Message message : messages){ | ||
messageList.add(messageMapper.convertToMessageResponseDto(message)); | ||
} | ||
return messageList; | ||
} | ||
} |
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
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
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
33 changes: 33 additions & 0 deletions
33
src/main/java/com/book/backend/global/stomp/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,33 @@ | ||
package com.book.backend.global.stomp; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.messaging.simp.config.MessageBrokerRegistry; | ||
import org.springframework.web.socket.config.annotation.EnableWebSocket; | ||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; | ||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; | ||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; | ||
|
||
@Configuration | ||
@EnableWebSocket | ||
@RequiredArgsConstructor | ||
@EnableWebSocketMessageBroker | ||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { | ||
/* | ||
request URL = ws://localhost:8080/ws-stomp | ||
Destination (발신 URL) = /pub/message | ||
Subscription (수신 URL) = /sub/message/{opentalkId} | ||
*/ | ||
@Override | ||
public void registerStompEndpoints(final StompEndpointRegistry registry) { | ||
registry.addEndpoint("/ws-stomp") | ||
.setAllowedOriginPatterns("*"); | ||
} | ||
|
||
@Override | ||
public void configureMessageBroker(final MessageBrokerRegistry registry) { | ||
registry.setApplicationDestinationPrefixes("/pub"); // 발행요청 | ||
registry.enableSimpleBroker("/sub"); // 구독요청 | ||
} | ||
} |