feat : rabbitmq 추가 완료

This commit is contained in:
yulmam 2024-07-31 12:52:40 +09:00
parent c94827259f
commit b9cc9b8a50
8 changed files with 186 additions and 98 deletions

View File

@ -0,0 +1,13 @@
package com.edufocus.edufocus.global.config;
import com.edufocus.edufocus.global.properties.RabbitMQProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties({
RabbitMQProperties.class
})
public class PropertiesConfig {
}

View File

@ -0,0 +1,15 @@
package com.edufocus.edufocus.global.constant;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum RabbitMQConstant {
CHAT_QUEUE_NAME("chat.queue"),
CHAT_EXCHANGE("chat.exchange"),
ROUTING_KEY("*.room.*"),
ROUTING_KEY_PREFIX("*.room.");;
private final String constant;
}

View File

@ -0,0 +1,16 @@
package com.edufocus.edufocus.global.properties;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Getter
@RequiredArgsConstructor
@ConfigurationProperties(prefix = "spring.rabbitmq")
public class RabbitMQProperties {
private final String host;
private final Integer port;
private final String username;
private final String password;
}

View File

@ -14,39 +14,38 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer {
// private JWTInterceptor jwtInterceptor;
//
// public WebConfiguration(JWTInterceptor jwtInterceptor) {
// super();
//
// this.jwtInterceptor = jwtInterceptor;
// }
//
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry
// .addMapping("/**")
// .allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173")
// .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(),
// HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(),
// HttpMethod.PATCH.name())
// .allowCredentials(true)
// .allowedHeaders("*")
// .maxAge(1800); // Pre-flight Caching
// }
//
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/");
// registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/");
// }
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(jwtInterceptor)
//
// .addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용
// .excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**"); // 인증 없이 접근 가능한 경로 설정
//
// ///v3/api-docs/**, /swagger-resources/**, /webjars/**
// }
private JWTInterceptor jwtInterceptor;
public WebConfiguration(JWTInterceptor jwtInterceptor) {
super();
this.jwtInterceptor = jwtInterceptor;
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins("http://i11a701.p.ssafy.io/", "http://localhost:5173", "http://localhost:4173")
.allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.PUT.name(),
HttpMethod.DELETE.name(), HttpMethod.HEAD.name(), HttpMethod.OPTIONS.name(),
HttpMethod.PATCH.name())
.allowCredentials(true)
.allowedHeaders("*")
.maxAge(1800); // Pre-flight Caching
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/assets/img/");
registry.addResourceHandler("/*.html**").addResourceLocations("classpath:/static/");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/**") // 모든 경로에 대해 인터셉터 적용
.excludePathPatterns("/v3/api-docs/**","/swagger-resources/**","/webjars/**","/swagger-ui/**","/auth/**", "/board/**", "/user/**","/lecture/**","/qna/**", "/quiz/**"); // 인증 없이 접근 가능한 경로 설정
///v3/api-docs/**, /swagger-resources/**, /webjars/**
}
}

View File

@ -1,2 +1,73 @@
package com.edufocus.edufocus.ws.config;public class RabbitConfig {
package com.edufocus.edufocus.ws.config;
import com.edufocus.edufocus.global.constant.RabbitMQConstant;
import com.edufocus.edufocus.global.properties.RabbitMQProperties;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
private final RabbitMQProperties rabbitMQProperties;
public RabbitConfig(RabbitMQProperties rabbitMQProperties) {
this.rabbitMQProperties = rabbitMQProperties;
}
@Bean
public Queue queue() {
return new Queue(RabbitMQConstant.CHAT_QUEUE_NAME.getConstant(), true);
}
@Bean
public TopicExchange exchange() {
return new TopicExchange(RabbitMQConstant.CHAT_EXCHANGE.getConstant());
}
@Bean
Binding binding(TopicExchange topicExchange, Queue queue) {
return BindingBuilder.bind(queue).to(topicExchange).with(RabbitMQConstant.ROUTING_KEY.getConstant());
}
@Bean
ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost(rabbitMQProperties.getHost());
connectionFactory.setPort(rabbitMQProperties.getPort());
connectionFactory.setUsername(rabbitMQProperties.getUsername());
connectionFactory.setPassword(rabbitMQProperties.getPassword());
return connectionFactory;
}
@Bean
public AmqpAdmin amqpAdmin() {
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());
rabbitAdmin.declareQueue(queue());
return rabbitAdmin;
}
@Bean
MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter);
return rabbitTemplate;
}
}

View File

@ -1,7 +1,9 @@
package com.edufocus.edufocus.ws.config;
import com.edufocus.edufocus.global.properties.RabbitMQProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@ -10,15 +12,23 @@ import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerCo
@EnableWebSocketMessageBroker
public class WebSocketConfigurer implements WebSocketMessageBrokerConfigurer {
private final RabbitMQProperties rabbitMQProperties;
public WebSocketConfigurer(RabbitMQProperties rabbitMQProperties) {
this.rabbitMQProperties = rabbitMQProperties;
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setPathMatcher(new AntPathMatcher("."));
registry.setApplicationDestinationPrefixes("/pub")
.enableStompBrokerRelay("/topic")
.setRelayHost("localhost")
.enableStompBrokerRelay("/topic", "/queue", "/exchange")
.setRelayHost(rabbitMQProperties.getHost())
.setVirtualHost("/")
.setRelayPort(61613)
.setClientLogin("guest")
.setClientPasscode("guest");
.setClientLogin(rabbitMQProperties.getUsername())
.setClientPasscode(rabbitMQProperties.getPassword());
}
@Override

View File

@ -1,11 +1,13 @@
package com.edufocus.edufocus.ws.controller;
import com.edufocus.edufocus.global.constant.RabbitMQConstant;
import com.edufocus.edufocus.user.util.JWTUtil;
import com.edufocus.edufocus.ws.entity.dto.MessageDto;
import com.edufocus.edufocus.ws.entity.dto.QuizDto;
import com.edufocus.edufocus.ws.entity.dto.ChatUserDto;
import com.edufocus.edufocus.ws.service.ChatService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -30,70 +32,26 @@ import java.util.List;
@RestController
public class ChatController {
private final SimpMessageSendingOperations simpMessageSendingOperations;
RabbitTemplate rabbitTemplate;
private final ChatService chatService;
private final JWTUtil jwtUtil;
public ChatController(SimpMessageSendingOperations simpMessageSendingOperations, ChatService chatService, JWTUtil jwtUtil){
this.simpMessageSendingOperations = simpMessageSendingOperations;
this.chatService = chatService;
this.jwtUtil = jwtUtil;
public ChatController(RabbitTemplate rabbitTemplate){
this.rabbitTemplate = rabbitTemplate;
}
@GetMapping("/chat/enter/{lectureId}")
public ResponseEntity<?> enter(@PathVariable long lectureId){
List<ChatUserDto> chatUsers = chatService.findChatUsers(lectureId);
@MessageMapping("chat.message.{lectureId}")
public void sendMessage(@DestinationVariable long lectureId, MessageDto messageDto){
rabbitTemplate.convertAndSend(RabbitMQConstant.CHAT_EXCHANGE.getConstant(),
RabbitMQConstant.ROUTING_KEY_PREFIX.getConstant() + lectureId,
messageDto);
}
return new ResponseEntity<>(chatUsers, HttpStatus.OK);
@MessageMapping("chat.quiz.{lectureId}")
public void quizStart(@DestinationVariable long lectureId, QuizDto quizDto){
rabbitTemplate.convertAndSend(RabbitMQConstant.CHAT_EXCHANGE.getConstant(),
RabbitMQConstant.ROUTING_KEY_PREFIX.getConstant() + lectureId,
quizDto);
}
@MessageMapping("/hello/{channelId}")
@SendTo("/topic/{channelId}")
public ChatUserDto hello(@DestinationVariable long channelId, SimpMessageHeaderAccessor simpMessageHeaderAccessor, @Header("Authorization") String token){
String sessionId = simpMessageHeaderAccessor.getSessionId();
System.out.println("session" + sessionId);
System.out.println("가냐?????"+token);
long userId = Long.parseLong(jwtUtil.getUserId(token));
chatService.saveChatUserInfo(userId, channelId, sessionId);
return chatService.getChatUserInfo(userId);
}
@MessageMapping("/message/{lectureId}")
@SendTo("/topic/{lectureId}")
public MessageDto sendMessage(@DestinationVariable long lectureId, MessageDto messageDto){return messageDto;}
@MessageMapping("/quiz/{lectureId}")
@SendTo("/topic/{lectureId}")
public QuizDto quizStart(@DestinationVariable long lectureId, QuizDto quizDto){
return quizDto;
}
// @EventListener
// public void handleWebSocketDisconnectListener(SessionDisconnectEvent event){
// StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
// String sessionId = headerAccessor.getSessionId();
//
//
// ChatUserDto chatUserDto = chatService.getChatUserInfo(sessionId);
//
//
// if(chatService.checkTeacher(chatUserDto)){
// chatService.closeChatRoom(chatUserDto.getLectureId());
// simpMessageSendingOperations.convertAndSend("/sub/channel/" + chatUserDto.getLectureId(), "강의가 종료 됐습니다.");
// return;
// }
//
// chatService.deleteChatUserInfo(chatUserDto.getUserId());
// simpMessageSendingOperations.convertAndSend("/sub/channel/" + chatUserDto.getLectureId(), chatUserDto);
// }
}

View File

@ -37,3 +37,9 @@ spring.mail.password=mnlyfkiprltjlsmw
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.rabbitmq.host=${RABBITMQ_HOST}
spring.rabbitmq.port=${RABBITMQ_PORT}
spring.rabbitmq.username=${RABBITMQ_USERNAME}
spring.rabbitmq.password=${RABBITMQ_PASSWORD}