redis-动态创建pub-sub
一般的 在使用 spring boot时,使用 RedisMessageListenerContainer 来绑定发布订阅时,topic和listener 关系
@Autowired
private HelloListener helloListener;
//创建topic
@Bean
public ChannelTopic channelTopic() {
return new ChannelTopic("a");
}
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
//在这里绑定topic和listener关系
container.addMessageListener(helloListener, channelTopic());
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//json转对象类,不设置默认的会将json转成hashmap
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
container.setTopicSerializer(jackson2JsonRedisSerializer);
return container;
}
HelloListener
@Component
public class HelloListener implements MessageListener {
@Autowired
private ObjectMapper objectMapper;
@Override
public void onMessage(Message message, byte[] pattern) {
String str = new String(message.getBody(), StandardCharsets.UTF_8);
System.out.println(str);
try {
ProductSub product = objectMapper.readValue(str, ProductSub.class);
System.out.println(objectMapper.writeValueAsString(product));
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面进行动态创建 topic
@GetMapping("/pub")
public String pub(@RequestParam String topic) throws Exception {
ProductSub product = new ProductSub();
product.setId(1);
product.setName("hello from me");
product.setPrice(12);
String str = mapper.writeValueAsString(product);
System.out.println("send: " + str);
redisTemplate.convertAndSend(topic, str);
return "success";
}
@GetMapping("/pub/channel/create")
public String createChannel(@RequestParam String topic) {
ChannelTopic ct = new ChannelTopic(topic);
container.addMessageListener(listener, ct);
return "success";
}
显然,这种方式可以创建topic,但不能动态绑定topic和listener的关系
RedisClient
通过 RedisClient 来动态创建pub-sub
@Bean
public RedisClient redisClient(ClientResources clientResources) {
RedisURI redisURI = RedisURI.create("redis://192.1xx.x.10");
return RedisClient.create(clientResources, redisURI);
}
动态创建
@Autowired
private RedisClient redisClient;
@GetMapping("/pub/channel/create2")
public String createChannel2(@RequestParam String topic) {
StatefulRedisPubSubConnection<String, String> pubSubConnection = redisClient.connectPubSub();
pubSubConnection.addListener(dynamicListener);
pubSubConnection.async().subscribe(topic);
return "success";
}
@GetMapping("/pub2")
public String pub2(@RequestParam String topic) throws Exception {
ProductSub product = new ProductSub();
product.setId(1);
product.setName("hello from me");
product.setPrice(12);
String str = mapper.writeValueAsString(product);
System.out.println("send: " + str);
RedisPubSubAsyncCommands<String, String> pubSubAsyncCommands = redisClient.connectPubSub().async();
pubSubAsyncCommands.publish(topic, mapper.writeValueAsString(product));
return "success";
}
DynamicListener
@Service
@Slf4j
public class DynamicListener implements RedisPubSubListener {
@Override
public void message(Object channel, Object message) {
log.info(">>>>>> message channel:{}-msg:{}", channel, message);
}
@Override
public void message(Object pattern, Object channel, Object message) {
log.info(">>>> message pattern:{}-channel:{}-msg:{}", pattern, channel, message);
}
@Override
public void subscribed(Object channel, long count) {
log.info(">>>> subscribed channel:{}-count:{}", channel, count);
}
@Override
public void psubscribed(Object pattern, long count) {
log.info(">>>>> psubscribed pattern:{}-count:{}", pattern, count);
}
@Override
public void unsubscribed(Object channel, long count) {
log.info(">>>> unsubscribed channel:{}-count:{}", channel, count);
}
@Override
public void punsubscribed(Object pattern, long count) {
log.info(">>>>> punsubscribed pattern:{}-count:{}", pattern, count);
}
}
结果:
#/pub/channel/create2
>>>> subscribed channel:c-count:1
# /pub2
>>>>>> message channel:c-msg:{"id":1,"name":"hello from me","price":12}
查看主题
dc-10:0>pubsub channels
1) "c" # 刚刚创建
2) "a"
pub-sub查看命令
查看频道:
pubsub channels
通配符匹配:
pubsub channels key*
查看订阅数:
pubsub numsub key1 key2