近期,项目升级依赖包到SpringBoot 2.0.1, 原有的spring-data-redis也默认自动升级为2.0.6, 其中重要一点是原有jedis驱动修改为lettuce驱动了。 关于jedis和lettuce比较,本文就不再赘述,综合来看肯定倾向于选择使用lettuce驱动,不管您是否使用spring-data-redis。
简要介绍
第一种,使用spring-data-redis自带的org.springframework.data.redis.connection.MessageListener作为消息接收类的父类。
优势,如果原来使用jedis驱动时也是使用MessageListener, 基本上不用改动任何代码,就可以继续使用。
我们使用spring-data-redis的RedisConnection , 在订阅是绑定MessageListener的具体实现类就行
RedisConnection redisConnection = lettuceConnectionFactory.getConnection();
redisConnection.subscribe(new MyMessageListener(), channel.getBytes(StandardCharsets.UTF_8) );
Long count = redisConnection.publish(channel.getBytes(StandardCharsets.UTF_8), "1st".getBytes(StandardCharsets.UTF_8));
第二种,使用io.lettuce.core.pubsub.RedisPubSubListener作为消息接收类的父类。
这个RedisPubSubListener类就如同redis.clients.jedis.JedisPubSub类一样。这种方式必须使用原生的StatefulRedisPubSubConnection,因此必须重新连接redis(通过RedisClient ),当然生产环境中我们可以通过连接池进行连接,这里是示例代码,就不适用pool了,也没有关闭操作。
RedisClient client = RedisClient.create("redis://127.0.0.1");
StatefulRedisPubSubConnection<String, String> connection = client.connectPubSub();
connection.addListener(new MyRedisPubSubListener());
RedisPubSubAsyncCommands<String, String> async = connection.async();
async.subscribe(channel);
代码
完整的代码在这里, 欢迎加星fork, 谢谢
A, 使用spring-data-redis自带的org.springframework.data.redis.connection.MessageListener;作为消息接收类的父类。
package com.yq.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.lang.Nullable;
/**
* Simple to Introduction
* className: MyMessageListener
*
* @author EricYang
* @version 2019/2/23 13:16
*/
@Slf4j
public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message, @Nullable byte[] pattern) {
byte[] bytesBody = message.getBody();
byte[] bytesChannel = message.getChannel();
log.info("msgBody={}, channel={}, pattern={}", bytesBody!=null? new String(bytesBody): null, bytesChannel!=null? new String(bytesChannel): null, pattern);
}
}
B, 使用io.lettuce.core.pubsub.RedisPubSubListener;作为消息接收类的父类。
package com.yq.service;
import io.lettuce.core.pubsub.RedisPubSubListener;
import lombok.extern.slf4j.Slf4j;
/**
* Simple to Introduction
* className: MyRedisPubSubListener
*
* @author EricYang
* @version 2019/2/22 14:08
*/
@Slf4j
public class MyRedisPubSubListener implements RedisPubSubListener<String, String> {
@Override
public void message(String channel, String message) {
log.info("msg1={} on channel {}", message, channel);
}
@Override
public void message(String pattern, String channel, String message) {
log.info("msg2={} in channel={}", message, channel);
}
@Override
public void subscribed(String channel, long count) {
log.info("sub channel={}, count={}", channel, count);
}
@Override
public void psubscribed(String pattern, long count) {
log.info("psub pattern={}, count={}", pattern, count);
}
@Override
public void unsubscribed(String channel, long count) {
log.info("unsub channel={}, count={}", channel, count);
}
@Override
public void punsubscribed(String pattern, long count) {
log.info("punsub channel={}, count={}", pattern, count);
}
}
效果截图
截图说明,按照截图中的,我们使用两种不同的方式订阅channel1,然后通过API或者redis命令行给channel1发送消息,可以看到两个listener都可以收到通知。
程序日志
注意事项:
1, 订阅pattern时,确保你的redis开启了对应通知,否则订阅虽然成功了,但是不会收到通知。