Skip to content

Commit e889afd

Browse files
authored
Merge pull request #2 from codej99/feature/pubsub
Feature/pubsub
2 parents 445d9e2 + 227b627 commit e889afd

File tree

7 files changed

+147
-5
lines changed

7 files changed

+147
-5
lines changed

src/main/java/com/redis/cluster/config/RedisCacheConfig.java

+19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import org.springframework.data.redis.cache.RedisCacheConfiguration;
99
import org.springframework.data.redis.cache.RedisCacheManager;
1010
import org.springframework.data.redis.connection.RedisConnectionFactory;
11+
import org.springframework.data.redis.core.RedisTemplate;
12+
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
13+
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
1114
import org.springframework.data.redis.serializer.RedisSerializationContext;
1215
import org.springframework.data.redis.serializer.StringRedisSerializer;
1316

@@ -36,4 +39,20 @@ public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory)
3639
return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory).cacheDefaults(configuration)
3740
.withInitialCacheConfigurations(cacheConfigurations).build();
3841
}
42+
43+
@Bean
44+
public RedisMessageListenerContainer RedisMessageListener(RedisConnectionFactory connectionFactory) {
45+
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
46+
container.setConnectionFactory(connectionFactory);
47+
return container;
48+
}
49+
50+
@Bean
51+
public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {
52+
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
53+
redisTemplate.setConnectionFactory(connectionFactory);
54+
redisTemplate.setKeySerializer(new StringRedisSerializer());
55+
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
56+
return redisTemplate;
57+
}
3958
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.redis.cluster.controller;
2+
3+
import com.redis.cluster.pubsub.RedisPublisher;
4+
import com.redis.cluster.pubsub.RedisSubscriber;
5+
import com.redis.cluster.pubsub.RoomMessage;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.data.redis.listener.ChannelTopic;
8+
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
9+
import org.springframework.web.bind.annotation.*;
10+
11+
import javax.annotation.PostConstruct;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
import java.util.Set;
15+
16+
@RequiredArgsConstructor
17+
@RequestMapping("/pubsub")
18+
@RestController
19+
public class PubSubController {
20+
// topic에 발행되는 액션을 처리할 Listner
21+
private final RedisMessageListenerContainer redisMessageListener;
22+
// 발행자
23+
private final RedisPublisher redisPublisher;
24+
// 구독자
25+
private final RedisSubscriber redisSubscriber;
26+
// 특정 topic에 메시지를 발송할 수 있도록 topic정보를 Map에 저장
27+
private Map<String, ChannelTopic> channels;
28+
29+
@PostConstruct
30+
public void init() {
31+
// 실행될때 topic정보를 담을 Map을 초기화
32+
channels = new HashMap<>();
33+
}
34+
35+
// 유효한 Topic 리스트 반환
36+
@GetMapping("/room")
37+
public Set<String> findAllRoom() {
38+
return channels.keySet();
39+
}
40+
41+
// Topic 생성하여 Listener에 등록후 Topic Map에 저장
42+
@PutMapping("/room/{roomId}")
43+
public void createRoom(@PathVariable String roomId) {
44+
ChannelTopic channel = new ChannelTopic(roomId);
45+
redisMessageListener.addMessageListener(redisSubscriber, channel);
46+
channels.put(roomId, channel);
47+
}
48+
49+
// 특정 Topic에 메시지 발송
50+
@PostMapping("/room/{roomId}")
51+
public void pushMessage(@PathVariable String roomId, @RequestParam String name, @RequestParam String message) {
52+
ChannelTopic channel = channels.get(roomId);
53+
redisPublisher.publish(channel, RoomMessage.builder().name(name).roomId(roomId).message(message).build());
54+
}
55+
56+
// 특정 Topic 삭제 후 Listener 해제
57+
@DeleteMapping("/room/{roomId}")
58+
public void deleteRoom(@PathVariable String roomId) {
59+
ChannelTopic channel = channels.get(roomId);
60+
redisMessageListener.removeMessageListener(redisSubscriber, channel);
61+
channels.remove(roomId);
62+
}
63+
}

src/main/java/com/redis/cluster/controller/RedisController.java

-3
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,18 @@ public User findOne(@PathVariable long msrl) {
2323
}
2424

2525
@PostMapping("/user")
26-
@ResponseBody
2726
public User postUser(@RequestBody User user) {
2827
return userJpaRepo.save(user);
2928
}
3029

3130
@CachePut(value = CacheKey.USER, key = "#user.msrl")
3231
@PutMapping("/user")
33-
@ResponseBody
3432
public User putUser(@RequestBody User user) {
3533
return userJpaRepo.save(user);
3634
}
3735

3836
@CacheEvict(value = CacheKey.USER, key = "#msrl")
3937
@DeleteMapping("/user/{msrl}")
40-
@ResponseBody
4138
public boolean deleteUser(@PathVariable long msrl) {
4239
userJpaRepo.deleteById(msrl);
4340
return true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.redis.cluster.pubsub;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.data.redis.core.RedisTemplate;
5+
import org.springframework.data.redis.listener.ChannelTopic;
6+
import org.springframework.stereotype.Service;
7+
8+
@RequiredArgsConstructor
9+
@Service
10+
public class RedisPublisher {
11+
12+
private final RedisTemplate<String, Object> redisTemplate;
13+
14+
public void publish(ChannelTopic topic, RoomMessage message) {
15+
redisTemplate.convertAndSend(topic.getTopic(), message);
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.redis.cluster.pubsub;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.springframework.data.redis.connection.Message;
7+
import org.springframework.data.redis.connection.MessageListener;
8+
import org.springframework.data.redis.core.RedisTemplate;
9+
import org.springframework.stereotype.Service;
10+
11+
@Slf4j
12+
@RequiredArgsConstructor
13+
@Service
14+
public class RedisSubscriber implements MessageListener {
15+
16+
private final ObjectMapper objectMapper;
17+
private final RedisTemplate redisTemplate;
18+
19+
@Override
20+
public void onMessage(Message message, byte[] pattern) {
21+
try {
22+
String body = (String) redisTemplate.getStringSerializer().deserialize(message.getBody());
23+
RoomMessage roomMessage = objectMapper.readValue(body, RoomMessage.class);
24+
log.info("Room - Message : {}", roomMessage.toString());
25+
} catch (Exception e) {
26+
log.error(e.getMessage());
27+
}
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.redis.cluster.pubsub;
2+
3+
import lombok.*;
4+
5+
import java.io.Serializable;
6+
7+
@Getter
8+
@Builder
9+
@NoArgsConstructor
10+
@AllArgsConstructor
11+
@ToString
12+
public class RoomMessage implements Serializable {
13+
private static final long serialVersionUID = 2082503192322391880L;
14+
private String roomId;
15+
private String name;
16+
private String message;
17+
}

src/main/resources/application.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ server:
33

44
logging:
55
level:
6-
root: warn
6+
root: info
77
com.rest.api: debug
88

99
spring:
@@ -28,4 +28,4 @@ spring:
2828
- 15.164.98.87:6401
2929
- 15.164.98.87:6402
3030
max-redirects: 3
31-
password: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
31+
password: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

0 commit comments

Comments
 (0)