Redis 訂閱發(fā)布_Jedis實(shí)現(xiàn)方法
我想到使用Redis的訂閱發(fā)布模式是用來解決推送問題的~。
對(duì)于概念性的敘述,多多少少還是要提一下的:
什么是Redis發(fā)布訂閱?Redis發(fā)布訂閱是一種消息通信模式,發(fā)送者通過通道A發(fā)送消息message,訂閱過通道A的客戶端就可以接收到消息message。嗯度娘上面的解釋要比我所說的好多了,而我所理解的就是:所謂的訂閱發(fā)布模式,其實(shí)和我們看電視,聽廣播差不多,在我們沒有調(diào)臺(tái)(換頻道)的時(shí)候,那個(gè)頻道也是在傳遞消息的(發(fā)布)。我們換到那個(gè)頻道上(訂閱)就能接收到消息了。是的,雖然可能有些不恰當(dāng)~
說明
本文中示例采用了三個(gè)客戶端,以“品”字形排列,由上至下,由左至右分別為客戶端1(c1),客戶端2(c2),客戶端3(c3).特此說明。
Redis訂閱與發(fā)布命令
首先聲明,有關(guān)Redis服務(wù)器的搭建工作,請(qǐng)自行查閱相關(guān)資料進(jìn)行環(huán)境搶建
聽說Redis中發(fā)布與訂閱只有簡(jiǎn)單的6個(gè)命令。即:
PSUBSCRIBE pattern [pattern ...]
訂閱一個(gè)或者多個(gè)符合pattern格式的頻道
PUBLISH channel message
發(fā)布消息到chanel中
PUBSUB subcommand [argument [argument ...]]
查看訂閱與發(fā)布系統(tǒng)狀態(tài)
PUNSUBSCRIBE [pattern [pattern ...]]
退訂所有符合格式的頻道
SUBSCRIBE channel [channel ...]
訂閱一個(gè)或者多個(gè)頻道
UNSUBSCRIBE [channel [channel ...]]
取消訂閱頻道
例1 - SUBSCRIBE
連接redis后鍵入命令
SUBSCRIBE study
這樣便訂閱了一個(gè)名為study的頻道。
接下來study頻道要發(fā)消息啦?!?/p>
例2 - PUBLISH
另開啟一個(gè)客戶端,我使用的是品字形布局的最上面那個(gè)做為發(fā)布者,鍵入
PUBLISH study "message1-go go go"
可以看到,當(dāng)客戶端1在study頻道發(fā)布消息時(shí),客戶端2(已訂閱study頻道)可以接收到c1發(fā)布的消息,而客戶端3由于沒有訂閱study頻道,所以接收不到c1發(fā)送的消息。
例3 - PSUBSCRIBE
現(xiàn)在,跟著博主左手,右手一個(gè)慢動(dòng)作。在c3中鍵入
PSUBSCRIBE study*
OK,現(xiàn)在在c1中鍵入
PUBLISH study "message2"
上結(jié)果圖:
c3采用的通配符的形式,也將study頻道給訂閱成功了。
接下來,在c1中繼續(xù)鍵入命令:
PUBLISH study:java "I hate java forever"
可以看到,使用psubscribe不僅將study頻道訂閱了,而且將以study為首的頻道也訂閱了。
例4 - PUBSUB
在c1中鍵入pubsub channel,可以獲得:
127.0.0.1:6379> PUBSUB channels 1) "study"
意為當(dāng)前正在活躍的頻道。
Jedis實(shí)現(xiàn)訂閱發(fā)布者模式
好了,上面通過命令行熟悉了一下Redis中有關(guān)訂閱發(fā)布者模式的相關(guān)命令。下面我們要將redis的訂閱與發(fā)布者嵌入到項(xiàng)目中。
首先,我們使用jedis先訂閱一個(gè)名為:study的頻道
然后我們先從命令行處進(jìn)行消息發(fā)布:
之后 ,我們使用jedis在項(xiàng)目中進(jìn)行消息發(fā)布:
我們可以進(jìn)行正常的通信 ~噢耶~
核心代碼:
PublishMessage.java 用于開啟一個(gè)發(fā)布消息的線程
private Logger logger = LoggerFactory.getLogger(PublishMessage.class); @Resource private JedisCluster jedisCluster; /** * 發(fā)布消息 * * @param channel 頻道 * @param message 信息 */ public void sendMessage(final String channel, final String message) { Thread thread = new Thread(() -> { Long publish = jedisCluster.publish(channel, message); logger.info("服務(wù)器在: {} 頻道發(fā)布消息{} - {}", channel, message, publish); }); logger.info("發(fā)布線程啟動(dòng):"); thread.setName("publishThread"); thread.start(); }
ChatSubscribe.java用于處理訂閱相關(guān)事件,繼承自JedisPubSub
private Logger logger = LoggerFactory.getLogger(ChatSubscribe.class); // 取得訂閱的消息后的處理 @Override public void onMessage(String channel, String message) { logger.info("訂閱成功,接收到的消息為:頻道-{},消息-{}", channel, message); RedisString.message = message; } // 取得按表達(dá)式的方式訂閱的消息后的處理 @Override public void onPMessage(String pattern, String channel, String message) { System.out.println("-----取得按表達(dá)式的方式訂閱的消息后的處理-----"); System.out.println(pattern + "=" + channel + "=" + message); } // 初始化按表達(dá)式的方式訂閱時(shí)候的處理 @Override public void onPSubscribe(String pattern, int subscribedChannels) { System.out.println("-----初始化按表達(dá)式的方式訂閱時(shí)候的處理-----"); System.out.println(pattern + "=" + subscribedChannels); } // 取消按表達(dá)式的方式訂閱時(shí)候的處理 @Override public void onPUnsubscribe(String pattern, int subscribedChannels) { System.out.println("-----取消按表達(dá)式的方式訂閱時(shí)候的處理-----"); System.out.println(pattern + "=" + subscribedChannels); } @Override public void onPong(String pattern) { super.onPong(pattern); } // 初始化訂閱時(shí)候的處理 @Override public void onSubscribe(String channel, int subscribedChannels) { logger.info("初始化訂閱信息:頻道-{},訂閱頻道-{}", channel, subscribedChannels); } // 取消訂閱時(shí)候的處理 @Override public void onUnsubscribe(String channel, int subscribedChannels) { logger.info("已取消訂閱頻道{}", channel); }
SubScribeMessage.java 訂閱頻道,取消頻道等動(dòng)作類
private Logger logger = LoggerFactory.getLogger(SubScribeMessage.class); private ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); @Resource private JedisCluster jedisCluster; /** * 訂閱頻道 * * @param channel 頻道 * @param roomSubListerner */ public void subscribeChannel(final String channel, final ChatSubscribe roomSubListerner) { cachedThreadPool.execute(new Runnable() { @Override public void run() { jedisCluster.subscribe(roomSubListerner, channel); } }); } jedisCluster是否封裝工具類,取自各位看官,核心代碼已給出,請(qǐng)各位看官根據(jù)自身業(yè)務(wù)與邏輯,自行更改與優(yōu)化代碼。 本次示例程序采用tomcat 9.0 + spring + springmvc 使用了諸如:@RestController,@GetMapping等相關(guān)注解,便于開發(fā),有興趣可自行查閱spring相關(guān)資料。
以上這篇Redis 訂閱發(fā)布_Jedis實(shí)現(xiàn)方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
hibernate-validator如何使用校驗(yàn)框架
高效、合理的使用hibernate-validator校驗(yàn)框架可以提高程序的可讀性,以及減少不必要的代碼邏輯,本文主要介紹了hibernate-validator如何使用校驗(yàn)框架,感興趣的可以了解一下2022-04-04SpringBoot集成H2內(nèi)存數(shù)據(jù)庫(kù)的方法
H2是Thomas Mueller提供的一個(gè)開源的、純java實(shí)現(xiàn)的關(guān)系數(shù)據(jù)庫(kù)。本文主要介紹了SpringBoot集成H2內(nèi)存數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,感興趣的可以了解一下2021-09-09Java實(shí)現(xiàn)兩人五子棋游戲(二) 畫出棋盤
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)兩人五子棋游戲,畫出五子棋的棋盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03MyBatis Plus更新對(duì)象無法設(shè)空值解決方案
這篇文章主要介紹了MyBatis Plus更新對(duì)象無法設(shè)空值解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11Java代碼性能測(cè)試實(shí)戰(zhàn)之ContiPerf安裝使用
這篇文章主要為大家介紹了Java代碼性能測(cè)試實(shí)戰(zhàn)之ContiPerf安裝使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06maven依賴關(guān)系中的<scope>provided</scope>使用詳解
這篇文章主要介紹了maven依賴關(guān)系中的<scope>provided</scope>使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07HttpClient實(shí)現(xiàn)表單提交上傳文件
這篇文章主要為大家詳細(xì)介紹了HttpClient實(shí)現(xiàn)表單提交上傳文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08