最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot整合Redis實(shí)現(xiàn)消息發(fā)布與訂閱的示例代碼

 更新時(shí)間:2022年08月09日 14:05:48   作者:羈客%  
能實(shí)現(xiàn)發(fā)送與接收信息的中間介有很多,比如:RocketMQ、RabbitMQ、ActiveMQ、Kafka等,本文主要介紹了Redis的推送與訂閱功能并集成Spring Boot的實(shí)現(xiàn),感興趣的可以了解一下

當(dāng)我們在多個(gè)集群應(yīng)用中使用到本地緩存時(shí),在數(shù)據(jù)庫數(shù)據(jù)得到更新后,為保持各個(gè)副本當(dāng)前被修改的數(shù)據(jù)與數(shù)據(jù)庫數(shù)據(jù)保持同步,在數(shù)據(jù)被操作后向其他集群應(yīng)用發(fā)出被更新數(shù)據(jù)的通知,使其刪除;下次當(dāng)其他應(yīng)用請求該被更新的數(shù)據(jù)時(shí),應(yīng)用會(huì)到數(shù)據(jù)庫去取,也就是最新的數(shù)據(jù),從而使得被更新數(shù)據(jù)與數(shù)據(jù)庫保持同步!

能實(shí)現(xiàn)發(fā)送與接收信息的中間介有很多,比如:RocketMQ、RabbitMQ、ActiveMQ、Kafka等,本次主要簡單介紹Redis的推送與訂閱功能并集成Spring Boot的實(shí)現(xiàn)。

1.添加SpringBoot 集成Redis maven依賴

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

2.配置Redis配置 RedisConfig.java

@Configuration
public class RedisConfig {
    @Value("${redis.server.nodes}")
    private String redisServerNodes;
 
    @Value("${redis.server.password}")
    private String redisServerPassword;
 
    //Redis集群配置,單機(jī)的redis注釋掉該方法,在application配置文件里面配置就可以了
    @Bean
    public RedisClusterConfiguration getRedisClusterConfiguration() {
 
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
 
        String[] serverArray = redisServerNodes.split(",");
        Set<RedisNode> nodes = new HashSet<RedisNode>();
        for (String ipPort : serverArray) {
            String[] ipAndPort = ipPort.split(":");
            nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.parseInt(ipAndPort[1])));
        }
        redisClusterConfiguration.setClusterNodes(nodes);
        RedisPassword pwd = RedisPassword.of(redisServerPassword);
        redisClusterConfiguration.setPassword(pwd);
        return redisClusterConfiguration;
    }
 
    //指定redisTemplate類型,如下為<String, Object>
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        // 使用JSON格式序列化對象,對緩存數(shù)據(jù)key和value進(jìn)行轉(zhuǎn)換
        Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
        // 解決查詢緩存轉(zhuǎn)換異常的問題
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(objectMapper);
 
        // 設(shè)置RedisTemplate模板API的序列化方式為JSON
        template.setDefaultSerializer(jacksonSeial);
        return template;
    }
 
     /**
     * Redis消息監(jiān)聽器容器
     * 這個(gè)容器加載了RedisConnectionFactory和消息監(jiān)聽器
     * 可添加多個(gè)不同話題的redis監(jiān)聽器,需要將消息監(jiān)聽器和消息頻道綁定,
     * 通過反射調(diào)用消息訂閱處理器的相關(guān)方法進(jìn)行業(yè)務(wù)處理
     *
     * @param  redisConnectionFactory       連接工廠
     * @param  listener                     Redis消息監(jiān)聽器
     * @param  MessageListenerAdapter       Redis消息監(jiān)聽適配器
     * @return RedisMessageListenerContainer    消息監(jiān)聽容器
     */
    @Bean
    @SuppressWarnings("all")
    public RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory,
                                                   RedisMessageListener listener,
                                                   MessageListenerAdapter adapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        // 所有的訂閱消息,都需要在這里進(jìn)行注冊綁定
        // new PatternTopic(TOPIC_NAME1) 表示發(fā)布信息的頻道
        // 可以添加多個(gè)頻道以及配置不同的頻道
        container.addMessageListener(listener, new PatternTopic(SystemConstants.TOPIC_NAME1));
        container.addMessageListener(adapter, new PatternTopic(SystemConstants.TOPIC_NAME2));
 
        /**
         * 設(shè)置序列化對象
         * 特別注意:1. 發(fā)布的時(shí)候和訂閱方都需要設(shè)置序列化
         *         2. 設(shè)置序列化對象必須放在 {加入消息監(jiān)聽器} 這步后面,不然接收器接收不到消息
         */
        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);
        container.setTopicSerializer(seria);
        return container;
    }
 
    /**
     * 這個(gè)地方是給messageListenerAdapter 傳入一個(gè)消息接受的處理器,利用反射的方法調(diào)用“receiveMessage”
     * 也有好幾個(gè)重載方法,這邊默認(rèn)調(diào)用處理器的方法 叫OnMessage
     *
     * @param redisMessageReceiver 消息接收對象
     * @return 消息監(jiān)聽適配器
     */
    @Bean
    public MessageListenerAdapter listenerAdapter(RedisMessageReceiver redisMessageReceiver) {
        MessageListenerAdapter receiveMessage = new MessageListenerAdapter(printMessageReceiver, "onMessage");
        Jackson2JsonRedisSerializer<Object> seria = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        seria.setObjectMapper(objectMapper);
        receiveMessage.setSerializer(seria);
        return receiveMessage;
    }
}

3.Redis的訂閱主要有兩種實(shí)現(xiàn)方式

方式一:編寫Redis監(jiān)聽類RedisMessageListener,實(shí)現(xiàn)Redis的監(jiān)聽接口MessageListener,并重寫onMessage方法

方式二:編寫Redis消息監(jiān)聽適配器類,并在RedisConfig.java中配置消息監(jiān)聽適配器bean

方式一 與 方式二 主要是實(shí)現(xiàn)訂閱Redis推送的消息后的具體操作,這兩種方式可以同時(shí)使用來訂閱多個(gè)頻道里的消息

//方式一:
@Slf4j
@Component
public class RedisMessageListener implements MessageListener {
 
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private CacheManager cacheManager;
 
    @Override
    public void onMessage(Message message, byte[] pattern) {
    // 接收的topic
    log.info("接收消息頻道:" + new String(pattern));
    //序列化對象(特別注意:發(fā)布的時(shí)候需要設(shè)置序列化;訂閱方也需要設(shè)置序列化)
    MessageDto<?> messageDto = (MessageDto<?>) redisTemplate.getValueSerializer().deserialize(message.getBody());
    //MessageDto<T>為自己編寫的一個(gè)消息對象類(如自定義有:String data,String title,T content 等屬性)
    log.info("接收消息內(nèi)容:{}", messageDto);
    //根據(jù)消息內(nèi)容做具體業(yè)務(wù)邏輯。。。。。。。。。
    //。。。。。。。。。。。。。。。。。。。。。。
    }
}
//方式二
@Slf4j
@Component
public class RedisMessageReceiver {
 
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
 
    /**
     * 方法命名規(guī)則必須為function(Object messageDto) / function(Object messageDto,String topic)
     * @param messageDto 消息對象
     * @param topic 消息頻道名稱
     */
    public void onMessage(Object messageDto , String topic) {
        // 接收消息頻道
        log.info("接收消息頻道:" + topic);
        //接收消息內(nèi)容
        log.info("接收消息內(nèi)容:{}",messageDto);
    }
}

4.編寫Redis消息的推送工具類,在需要推送消息的地方使用來向Redis推送消息(如:操作數(shù)據(jù)的地方)

@Slf4j
@Component
public class RedisMessageUtils {
 
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
 
    /**
     * 向通道發(fā)布消息
     */
    public void sendMessage(String topic, Object message) {
        if (!StringUtils.hasText(topic)) {
            return;
        }
        try {
            redisTemplate.convertAndSend(topic, message);
            log.info("發(fā)送消息成功,topic:{},message:{}", topic, message);
        } catch (Exception e) {
            log.info("發(fā)送消息失敗,topic:{},message:{}", topic, message);
            e.printStackTrace();
        }
    }
}

5.使用

@RestController
@RequestMapping("/user")
public class UserController{
 
  @Autowired
  private UserService userService;
 
  @PostMapping("/getUsers")  
  public List<User> queryUsers(@RequestBody UserDto userDto){
   List<User> users=userService.queryUsers(userDto);
   //發(fā)送測試消息
   RedisMessageUtils.sendMessage(SystemConstants.TOPIC_NAME2, new MessageDto());
   return users;
  }
}

成功示例:

2099-12-31 23:59:59.999 [http-nio-8888-exec-1] INFO  com.xxx.yyy.util.RedisMessageUtils : 發(fā)送消息成功,topic:TOPIC2,message:MessageDto(data=null, title=null, content=null)
2099-12-31 23:59:59.999 [container-2] INFO  com.xxx.yyy.zzz.RedisMessageReceiver : 接收消息頻道:TOPIC2
2099-12-31 23:59:59.999 [container-2] INFO  com.xxx.yyy.zzz.RedisMessageReceiver : 接收消息內(nèi)容:MessageDto(data=null, title=null, content=null)

以上就是SpringBoot整合Redis實(shí)現(xiàn)消息發(fā)布與訂閱的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Redis消息發(fā)布 訂閱的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java利用Calendar類打印日歷

    java利用Calendar類打印日歷

    這篇文章主要為大家詳細(xì)介紹了java利用Calendar類打印日歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的示例代碼

    Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下
    2022-09-09
  • Netty分布式NioEventLoop優(yōu)化selector源碼解析

    Netty分布式NioEventLoop優(yōu)化selector源碼解析

    這篇文章主要介紹了Netty分布式NioEventLoop優(yōu)化selector源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • idea 設(shè)置支持ES6語法的操作

    idea 設(shè)置支持ES6語法的操作

    這篇文章主要介紹了idea設(shè)置支持ES6語法的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 一文詳解Java中流程控制語句

    一文詳解Java中流程控制語句

    在一個(gè)程序執(zhí)行的過程中,各條語句的執(zhí)行順序?qū)Τ绦虻慕Y(jié)果是有直接影響的。也就是說,程序的流程對運(yùn)行結(jié)果有直接的影響。所以,我們必須清楚每條語句的執(zhí)行流程。本文就來通過一些示例帶大家詳細(xì)了解一下
    2022-10-10
  • 淺析Java設(shè)計(jì)模式編程中的單例模式和簡單工廠模式

    淺析Java設(shè)計(jì)模式編程中的單例模式和簡單工廠模式

    這篇文章主要介紹了淺析Java設(shè)計(jì)模式編程中的單例模式和簡單工廠模式,使用設(shè)計(jì)模式編寫代碼有利于團(tuán)隊(duì)協(xié)作時(shí)程序的維護(hù),需要的朋友可以參考下
    2016-01-01
  • SpringBoot?調(diào)用外部接口的三種實(shí)現(xiàn)方法

    SpringBoot?調(diào)用外部接口的三種實(shí)現(xiàn)方法

    Spring Boot調(diào)用外部接口的方式有多種,常見的有以下三種方式:RestTemplate、Feign 和 WebClient,本文就詳細(xì)介紹一下,感興趣的可以了解一下
    2023-08-08
  • idea 解決用骨架創(chuàng)建項(xiàng)目過慢的操作方式

    idea 解決用骨架創(chuàng)建項(xiàng)目過慢的操作方式

    這篇文章主要介紹了idea 解決用骨架創(chuàng)建項(xiàng)目過慢的操作方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Java基于logback?MessageConverter實(shí)現(xiàn)日志脫敏方案分析

    Java基于logback?MessageConverter實(shí)現(xiàn)日志脫敏方案分析

    本文介紹了一種日志脫敏方案,即基于logbackMessageConverter和正則匹配的方法,該方法的優(yōu)點(diǎn)是侵入性低,工作量少,只需修改xml配置文件,適用于老項(xiàng)目,感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • Java中判斷字符串是否相等的實(shí)現(xiàn)

    Java中判斷字符串是否相等的實(shí)現(xiàn)

    這篇文章主要介紹了Java中判斷字符串是否相等的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論

柞水县| 芦溪县| 娱乐| 临漳县| 东港市| 军事| 泗水县| 海阳市| 景宁| 昌乐县| 丰镇市| 永德县| 武宁县| 麻江县| 台中市| 黔江区| 定结县| 海丰县| 宜丰县| 泗洪县| 涞源县| 晋宁县| 闽清县| 宁国市| 鄂尔多斯市| 灵丘县| 区。| 雷山县| 信宜市| 麦盖提县| 怀化市| 临安市| 陵川县| 贺州市| 松原市| 泸西县| 安阳县| 黄陵县| 南汇区| 芒康县| 庄浪县|