1 분 소요

Redis에서 Pub/Sub을 지원합니다. 특정 topic에 메시지를 전송하는 것을 Springboot을 이용하여 구현하는 것을 알아봅니다.

application.yml 설정

spring:
  main.allow-circular-references: true
  application:
    name: redis-cluster
  redis:
     topic: ${MY_TOPIC:topic1}

ChatMessage Model

@Getter
@Setter
@ToString
public class ChatMessage {
    private String sender;
    private String context;
}

ChatMessage Dto

@Getter
@Setter
@ToString
public class ChatMessageDto {
    private String sender;
    private String context;
}

Subscribe Serivce

@Slf4j
@RequiredArgsConstructor
@Service
public class RedisSubService implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] pattern) {
    	log.info("받은 메시지 = {}, body={}, pattern:{}", message, new String(message.getBody()),  new String(pattern));
    }
}

Redis Configuration

@Configuration
public class RedisConfig {
  private final RedisTemplate<String, Object> redisTemplate;

	@Value("${spring.redis.topic}")
	private String topicName;

     :
    //리스너어댑터 설정
    @Bean
    MessageListenerAdapter messageListenerAdapter() {
        return new MessageListenerAdapter(new RedisSubService());
    }
    
    //컨테이너 설정
    @Bean
    RedisMessageListenerContainer redisContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory());
        container.addMessageListener(messageListenerAdapter(), topic());
        return container;
    }

    //pub/sub 토픽 설정
    @Bean
    ChannelTopic topic() {
        return new ChannelTopic(topicName);
    }
}

Publish Service

@Slf4j
@RequiredArgsConstructor
@Service
public class RedisPubService {
  private final RedisTemplate<String, Object> redisTemplate;

	@Value("${spring.redis.topic}")
	private String topicName;
	
	ObjectMapper objectMapper = new ObjectMapper();
    public void sendMessage(ChatMessage chatMessage) {
    	log.info("topicName:{}, Chat Message:{}", topicName, chatMessage);
    	try {
        redisTemplate.convertAndSend(topicName, objectMapper.writeValueAsString(chatMessage));
    	} catch(JsonProcessingException jpe) {
    		jpe.printStackTrace();
    	}
    }
}

Controller

@RequiredArgsConstructor
@RestController
public class PubSubController {
    private final RedisPubService redisPubService;

    @PostMapping("/api/chat")
    public String pubSub(@RequestBody ChatMessageDto chatMessageDto) {
        //메시지 보내기
    	ChatMessage chatMessage = new ChatMessage();
    	BeanUtils.copyProperties(chatMessageDto, chatMessage);
    	redisPubService.sendMessage(chatMessage);

      return "success";
    }
}

댓글남기기