Springboot2.0 集成redisTemplate實(shí)現(xiàn)發(fā)布/訂閱功能

Redis 不僅提供一個(gè)NoSQL數(shù)據(jù)庫燕耿,同時(shí)提供了一套消息系統(tǒng),在開發(fā)過程中憔晒,應(yīng)用場(chǎng)景非常多创千,根據(jù)不同的業(yè)務(wù)需求,可以實(shí)現(xiàn)相應(yīng)的功能皆串。
我的業(yè)務(wù)需求是淹办,在分布式系統(tǒng)中,當(dāng)其中一個(gè)節(jié)點(diǎn)產(chǎn)生一條消息時(shí)恶复,需要同時(shí)通知其他節(jié)點(diǎn)做相應(yīng)的處理怜森。

相關(guān)類的解釋:

RedisMessageListenerContainer

Redis訂閱發(fā)布的監(jiān)聽容器,通過Redis的消息發(fā)布谤牡、訂閱配置都在這里面實(shí)現(xiàn)

  • addMessageListener(MessageListenerAdapter副硅,PatternTopic) 新增訂閱頻道及訂閱者,訂閱者必須有相關(guān)方法處理收到的消息
  • setTopicSerializer(RedisSerializer) 對(duì)頻道內(nèi)容進(jìn)行序列化解析
MessageListenerAdapter

監(jiān)聽適配器

  • MessageListenerAdapter(Object , defaultListenerMethod) 創(chuàng)建監(jiān)聽適配器翅萤,綁定訂閱接收器和接收消息的方法
RedisTemplate

Redis模版類

  • convertAndSend(String channel, Object message) 發(fā)布者向Redis發(fā)布消息

一恐疲、新增依賴

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

二、Redis連接信息配置

spring:
   redis:
        host: 127.0.0.1
        port: 6381
        ### Redis數(shù)據(jù)庫索引(默認(rèn)為0)
        database: 0
        ### 連接超時(shí)時(shí)間(毫秒)
        timeout: 60000ms
        password:
        lettuce:
            pool:
                ### 最大連接數(shù)(使用負(fù)值表示沒有限制) 默認(rèn)8
                max-active: 8
                ### 最小空閑連接  默認(rèn)8
                min-idle: 0
                ### 連接池中的最大空閑連接 默認(rèn)8
                max-idle: 8
                ### 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
                max-wait: -1ms

三断序、RedisConfig核心類流纹,實(shí)現(xiàn)了Redis連接,訂閱以及發(fā)布配置

@Configuration
public class RedisConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        // valuevalue采用jackson序列化方式
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value采用jackson序列化方式
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        //開啟事務(wù)支持
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * Redis消息監(jiān)聽器容器
     * 可以添加多個(gè)監(jiān)聽不同話題的redis監(jiān)聽器违诗,只需要把消息監(jiān)聽器和相應(yīng)的消息訂閱處理器綁定漱凝,
     * 該消息監(jiān)聽器通過反射技術(shù)調(diào)用消息訂閱處理器的相關(guān)方法進(jìn)行一些業(yè)務(wù)處理
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setConnectionFactory(connectionFactory);

        /**
         * 加入消息監(jiān)聽器(可以加入多個(gè)主題監(jiān)聽器,監(jiān)聽器也可以監(jiān)聽多個(gè)主題)
         **/
        // 加入WebSocket監(jiān)聽器
        final String TOPIC_NAME = "TEST_TOPIC"; // 訂閱主題
        MessageListenerAdapter webSocketListenerAdapter = webSocketListenerAdapter();
        redisMessageListenerContainer.addMessageListener(webSocketListenerAdapter, new PatternTopic(TOPIC_NAME));

        /**
         * 設(shè)置序列化對(duì)象
         * 特別注意:1. 發(fā)布的時(shí)候需要設(shè)置序列化诸迟;訂閱方也需要設(shè)置序列化
         *                   2. 設(shè)置序列化對(duì)象必須放在[加入消息監(jiān)聽器]這一步后面茸炒,否則會(huì)導(dǎo)致接收器接收不到消息
         */
        Jackson2JsonRedisSerializer seria = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        seria.setObjectMapper(objectMapper);
        redisMessageListenerContainer.setTopicSerializer(seria);

        return redisMessageListenerContainer;
    }

    /**
     * 綁定WebSocket消息推送接收器和接收方法
     */
    @Bean
    public MessageListenerAdapter webSocketListenerAdapter() {
        WebSocketReceiver webSocketReceiver = new WebSocketReceiver(); // 消息接收器
        final String RECEIVE_MESSAGE_METHOD = "receiveMessage"; // 消息接收器的方法名稱
        return new MessageListenerAdapter(webSocketReceiver, RECEIVE_MESSAGE_METHOD);
    }
}

四、封裝消息對(duì)象

@Data
public class MessageDTO implements Serializable {
    private String type;
    private String title;
    private String content;
}

五阵苇、消息接收器

public class WebSocketReceiver {

    /**
     * 接收WebSocket推送的消息并處理
     * @param message
     */
    public void receiveMessage(String message) {
        //序列化對(duì)象(特別注意:發(fā)布的時(shí)候需要設(shè)置序列化壁公;訂閱方也需要設(shè)置序列化)
        Jackson2JsonRedisSerializer seria = new Jackson2JsonRedisSerializer(WebSocketMessageDTO.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        seria.setObjectMapper(objectMapper);
        MessageDTO message = (MessageDTO ) seria.deserialize(message.getBytes());
        // 接收到消息對(duì)象,自己實(shí)現(xiàn)相關(guān)的業(yè)務(wù)處理...
    }
}

六绅项、測(cè)試發(fā)布消息

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRedis {
    @Resource
    private RedisTemplate redisTemplate;
    @Test
    public void test() {
        final String TOPIC_NAME = "TEST_TOPIC"; // 訂閱主題
        MessageDTO message = new MessageDTO();
        message.setTitle("訂閱發(fā)布測(cè)試...");
        // 發(fā)布消息
        redisTemplate.convertAndSend(TOPIC_NAME, message);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末紊册,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子快耿,更是在濱河造成了極大的恐慌囊陡,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掀亥,死亡現(xiàn)場(chǎng)離奇詭異撞反,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)搪花,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門遏片,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘹害,“玉大人,你說我怎么就攤上這事吮便”恃剑” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵线衫,是天一觀的道長(zhǎng)凿可。 經(jīng)常有香客問我,道長(zhǎng)授账,這世上最難降的妖魔是什么枯跑? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮白热,結(jié)果婚禮上敛助,老公的妹妹穿的比我還像新娘。我一直安慰自己屋确,他們只是感情好纳击,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著攻臀,像睡著了一般焕数。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刨啸,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天堡赔,我揣著相機(jī)與錄音,去河邊找鬼设联。 笑死善已,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的离例。 我是一名探鬼主播换团,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼宫蛆!你這毒婦竟也來了艘包?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤耀盗,失蹤者是張志新(化名)和其女友劉穎辑甜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袍冷,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年猫牡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胡诗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖煌恢,靈堂內(nèi)的尸體忽然破棺而出骇陈,到底是詐尸還是另有隱情,我是刑警寧澤瑰抵,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布你雌,位于F島的核電站,受9級(jí)特大地震影響二汛,放射性物質(zhì)發(fā)生泄漏婿崭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一肴颊、第九天 我趴在偏房一處隱蔽的房頂上張望氓栈。 院中可真熱鬧,春花似錦婿着、人聲如沸授瘦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽提完。三九已至,卻和暖如春丘侠,著一層夾襖步出監(jiān)牢的瞬間徒欣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工婉陷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帚称,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓秽澳,卻偏偏與公主長(zhǎng)得像闯睹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子担神,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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