菜鸟教程:https://www.runoob.com/redis/redis-pub-sub.html
redis是一种缓存数据库,它也是C/S的结构,也就是客户端和服务端,一般来说,在java中,我们通常使用 jedis(客户端)去操作redis(服务端),这其中操作的时候,两者之间肯定要建立连接,就像数据库链接一样,在关系型数据库中,我们一般都维护一个连接池,以达到链接的复用,来省去建立连接和关闭连接的时间。所以在jedis中,同样也存在一个jedispool(jedis连接池)的概念,我们都是从池中去取连接使用。
模型图:
发布者:
public class Publisher extends Thread{
private final JedisPool jedisPool;
public Publisher(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Jedis jedis = jedisPool.getResource();//连接池中取出一个连接
//jedis.auth("root"); //设置redis服务密码
while (true) {
String line = null;
try {
line = reader.readLine();
if (!"quit".equals(line)) {
jedis.publish("mychannel", line); //从 mychannel 的频道上发布消息
} else {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class SecPublisher extends Thread{
private final JedisPool jedisPool;
public SecPublisher(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Jedis jedis = jedisPool.getResource();//连接池中取出一个连接
//jedis.auth("root"); //设置redis服务密码
while (true) {
String line = null;
try {
line = reader.readLine();
if (!"quit".equals(line)) {
jedis.publish("mychannel2", line); //从 mychannel 的频道上发布消息
} else {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
订阅者:
public class Subscriber extends Thread {
private final JedisPool jedisPool;
private final SubscriberListener subscriberListener = new SubscriberListener();
private final String channel = "mychannel";
private final String channel2 = "mychannel2";
public Subscriber(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public void run() {
Jedis jedis = null;
try {
jedis = jedisPool.getResource(); //取出一个连接
//jedis.auth("root"); //设置redis服务密码
jedis.subscribe(subscriberListener, channel,channel2); //通过subscribe 的api去订阅,入参是订阅者和频道名
} catch (Exception e) {
System.out.println("订阅失败");
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
订阅监听:
这里继承 JedisPubSub类,重写其方法。
public class SubscriberListener extends JedisPubSub {
//收到消息调用
public void onMessage(String channel, String message) {
System.out.println(String.format("接收到订阅的消息, 订阅频道: [%s], 消息: [%s]", channel, message));
}
//订阅消息调用
public void onSubscribe(String channel, int subscribedChannels) {
System.out.println(String.format("订阅成功, 频道: [%s], 订阅频道数: [%s]", channel, subscribedChannels));
}
//取消订阅调用,todo 取消订阅没有生效
public void onUnsubscribe(String channel, int subscribedChannels) {
System.out.println(String.format("取消订阅, 频道: [%s], 取消频道数: [%s]", channel, subscribedChannels));
}
}
发布demo:
public class PubDemo {
public static void main(String[] args) {
// 连接redis服务端
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379,10,"root");
System.out.println("redis连接池准备好");
Publisher publisher = new Publisher(jedisPool); //发布者
publisher.start();
}
}
public class SecPubDemo {
public static void main(String[] args) {
// 连接redis服务端
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379,10,"root");
System.out.println("redis连接池准备好");
SecPublisher publisher = new SecPublisher(jedisPool); //发布者
publisher.start();
}
}
订阅demo:
public class SubDemo {
public static void main(String[] args) {
// 连接redis服务端
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "127.0.0.1", 6379,10,"root");
System.out.println("redis连接池准备好");
Subscriber subThread = new Subscriber(jedisPool); //订阅者
subThread.start();
}
}