使用Spring Data Redis 發(fā)布訂閱消息

使用 Spring Data Redis 發(fā)布訂閱消息

1. 概述

在 Redis 中君丁,發(fā)布者并沒有將消息發(fā)送給特定的訂閱者女淑。是將發(fā)布的消息被劃分為通道牍蜂,并不知道會有哪些訂閱者(如果有的話)嫩海。

類似地早抠,訂閱者表示對一個或多個主題感興趣,并且只接收感興趣的消息碑韵,而不知道有哪些發(fā)布者(如果有的話)赡茸。

發(fā)布者和訂閱者的這種解耦可以實(shí)現(xiàn)更大的可伸縮性和更動態(tài)的網(wǎng)絡(luò)拓?fù)洹?/p>

2. Redis 配置

讓我們開始添加消息隊(duì)列所需的配置。

首先祝闻,我們將定義一個 MessageListenerAdapter占卧,其中包含名為 RedisMessageSubscriberMessageListener 接口的自定義實(shí)現(xiàn)。這個 bean 充當(dāng)發(fā)布-訂閱消息模型中的訂閱者:

@Bean
MessageListenerAdapter messageListener() { 
    return new MessageListenerAdapter(new RedisMessageSubscriber());
}

RedisMessageListenerContainer 是 Spring Data Redis 提供的一個類联喘。這是內(nèi)部調(diào)用的华蜒,根據(jù) Spring Data Redis 文檔 的說法 —— “處理監(jiān)聽、轉(zhuǎn)換和消息調(diào)度的底層細(xì)節(jié)豁遭“认玻”

@Bean
RedisMessageListenerContainer redisContainer() {
    RedisMessageListenerContainer container 
      = new RedisMessageListenerContainer(); 
    container.setConnectionFactory(jedisConnectionFactory()); 
    container.addMessageListener(messageListener(), topic()); 
    return container; 
}

我們還將使用定制的 MessagePublisher 接口和 RedisMessagePublisher 實(shí)現(xiàn)創(chuàng)建 bean。這樣堤框,我們可以有一個通用的消息發(fā)布 API域滥,并讓 Redis 實(shí)現(xiàn)采用 redisTemplatetopic 作為構(gòu)造函數(shù)參數(shù):

@Bean
MessagePublisher redisPublisher() { 
    return new RedisMessagePublisher(redisTemplate(), topic());
}

最后,我們將設(shè)置一個主題蜈抓,發(fā)布者將向其發(fā)送消息启绰,訂閱者將接收消息:

@Bean
ChannelTopic topic() {
    return new ChannelTopic("messageQueue");
}

3. 發(fā)布消息

3.1. 定義 MessagePublisher 接口

Spring Data Redis 沒有提供用于消息分發(fā)的 MessagePublisher 接口。:我們可以定義一個自定義接口沟使,它將在實(shí)現(xiàn)中使用 redisTemplate:

public interface MessagePublisher {
    void publish(String message);
}

3.2. RedisMessagePublisher 實(shí)現(xiàn)[

我們接下來提供 MessagePublisher 接口的實(shí)現(xiàn)委可,添加消息發(fā)布的細(xì)節(jié)并使用 redisTemplate 中的函數(shù)。

該模板包含了一組非常豐富的函數(shù)腊嗡,用于廣泛的操作—— 其中 convertAndSend 能夠通過主題向隊(duì)列發(fā)送消息:

public class RedisMessagePublisher implements MessagePublisher {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private ChannelTopic topic;

    public RedisMessagePublisher() {
    }

    public RedisMessagePublisher(
      RedisTemplate<String, Object> redisTemplate, ChannelTopic topic) {
      this.redisTemplate = redisTemplate;
      this.topic = topic;
    }

    public void publish(String message) {
        redisTemplate.convertAndSend(topic.getTopic(), message);
    }
}

如您所見着倾,發(fā)布者實(shí)現(xiàn)非常簡單。它使用 redisTemplateconvertAndSend() 方法格式化給定的消息并將其發(fā)布到配置的主題燕少。

主題實(shí)現(xiàn)了發(fā)布和訂閱語義:當(dāng)消息發(fā)布時卡者,它將發(fā)送給所有注冊偵聽該主題的訂閱者。

4. 訂閱消息

RedisMessageSubscriber 實(shí)現(xiàn)了 Spring Data Redis 提供的 MessageListener 接口:

@Service
public class RedisMessageSubscriber implements MessageListener {

    public static List<String> messageList = new ArrayList<String>();

    public void onMessage(Message message, byte[] pattern) {
        messageList.add(message.toString());
        System.out.println("Message received: " + message.toString());
    }
}

注意客们,還有第二個參數(shù) pattern崇决,在本例中我們沒有使用它。Spring Data Redis 文檔指出底挫,該參數(shù)表示“匹配通道的模式(如果指定)”恒傻,但它可以為 null

5. 發(fā)送與接收消息

現(xiàn)在我們把它們結(jié)合起來建邓。我們創(chuàng)建一個消息盈厘,然后使用 RedisMessagePublisher 發(fā)布它:

String message = "Message " + UUID.randomUUID();
redisMessagePublisher.publish(message);

當(dāng)我們調(diào)用 publish(message) 時,內(nèi)容被發(fā)送到 Redis官边,在那里它被路由到我們的發(fā)布者中定義的消息隊(duì)列主題沸手。然后將它分發(fā)給該主題的訂閱者外遇。

您可能已經(jīng)注意到 RedisMessageSubscriber 是一個偵聽器,它將自己注冊到隊(duì)列以檢索消息契吉。

消息到達(dá)時臀规,訂閱者定義的 onMessage() 方法被觸發(fā)。

在我們的例子中栅隐,我們可以通過檢查 RedisMessageSubscriber 中的 messageList 來驗(yàn)證我們已經(jīng)收到了已經(jīng)發(fā)布的消息:

RedisMessageSubscriber.messageList.get(0).contains(message)

6. 結(jié)論

在本文中,我們研究了使用Spring Data Redis 實(shí)現(xiàn)的發(fā)布/訂閱消息隊(duì)列玩徊。

上述示例的實(shí)現(xiàn)可以在 GitHub project 項(xiàng)目中找到租悄。


【注】本文譯自:PubSub Messaging with Spring Data Redis | Baeldung


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市恩袱,隨后出現(xiàn)的幾起案子泣棋,更是在濱河造成了極大的恐慌,老刑警劉巖畔塔,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件潭辈,死亡現(xiàn)場離奇詭異,居然都是意外死亡澈吨,警方通過查閱死者的電腦和手機(jī)把敢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谅辣,“玉大人修赞,你說我怎么就攤上這事∩=祝” “怎么了柏副?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蚣录。 經(jīng)常有香客問我割择,道長,這世上最難降的妖魔是什么萎河? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任荔泳,我火速辦了婚禮,結(jié)果婚禮上公壤,老公的妹妹穿的比我還像新娘换可。我一直安慰自己,他們只是感情好厦幅,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布沾鳄。 她就那樣靜靜地躺著,像睡著了一般确憨。 火紅的嫁衣襯著肌膚如雪译荞。 梳的紋絲不亂的頭發(fā)上瓤的,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音吞歼,去河邊找鬼圈膏。 笑死,一個胖子當(dāng)著我的面吹牛篙骡,可吹牛的內(nèi)容都是我干的稽坤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼糯俗,長吁一口氣:“原來是場噩夢啊……” “哼尿褪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起得湘,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤杖玲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后淘正,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體摆马,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年鸿吆,在試婚紗的時候發(fā)現(xiàn)自己被綠了囤采。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡惩淳,死狀恐怖斑唬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情黎泣,我是刑警寧澤恕刘,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站抒倚,受9級特大地震影響褐着,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜托呕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一含蓉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧项郊,春花似錦馅扣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春蓄喇,著一層夾襖步出監(jiān)牢的瞬間发侵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工妆偏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刃鳄,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓钱骂,卻偏偏與公主長得像叔锐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子见秽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容