springboot整合rabbitMq

下載rabbitmq

下載地址:https://www.rabbitmq.com/install-windows.html

如果需要看到圖形管理界面,還需要進行如下操作:

打開doc窗口,切換到rabbitmq的bin目錄,執行:rabbitmq-plugins enable rabbitmq_management即可。

springboot整合rabbitmq

1.新建一個maven工程:

2.引入rabbitmq的依賴:

3.配置項目的端口以及整合rabbitmq的配置,找到resources目錄下的application.properties文件,這裏我將它改成了yml文件:

到這裏,mq的整合就完成了,是不是很簡單?因爲springboot本身就對mq做了集成,所以配置纔會很簡單,下面來介紹一下rabbitmq的集中消息模式。

常量類:
 

package com.ymy.utils;

/**
 * 消息隊列的常量
 */
public class RabbitConstant {

    /**
     * 普通的消息隊列,參數爲字符串
     */
    public static final String TEST_QUEUE = "test_queue";

    /**
     * 普通的消息隊列,參數爲對象
     */
    public static final String TEST_QUEUE_OBJECT = "test_queue_object";


    /**
     * 交換機----direct
     */
    public static final String EXCHANGE_DIRECT = "exchange_direct";


    /**
     * 綁定到叫環境(direct)的普通隊列
     */
    public static final String TEST_QUEUE_BIND_DIRECT1 = "test_queue_bind_direct1";


    /**
     * 綁定到叫環境(direct)的普通隊列
     */
    public static final String TEST_QUEUE_BIND_DIRECT2 = "test_queue_bind_direct2";


    /**
     * 交換機(direct)的路由key
     */
    public static final String DIRECT_EXCHANGE_ROUTING_KEY = "direct_exchange_routing_key";

    /**
     * 普通隊列1(用戶綁定到交換機fanout上)
     */
    public static final String TEST_QUEUE_TO_FANOUT1 = "test_queue_to_fanout1";

    /**
     * 普通隊列2(用戶綁定到交換機fanout上)
     */
    public static final String TEST_QUEUE_TO_FANOUT2 = "test_queue_to_fanout2";

    /**
     * 交換機(fanout)
     */
    public static final String FANOUT_EXCHANGE = "fanout_exchange";



    /**
     * 普通隊列1(用戶綁定到交換機topic上)
     */
    public static final String TEST_QUEUE_TO_TOPIC1 = "topic.message1";


    /**
     * 普通隊列2(用戶綁定到交換機topic上)
     */
    public static final String TEST_QUEUE_TO_TOPIC2 = "topic.message2";

    /**
     * 交換機(topic)
     */
    public static final String TOPIC_EXCHANGE = "topic_exchange";


    /**
     * 路由key(topic)
     */
    public static final String TOPIC_EXCHANGE_ROUTING_KEY = "topic.#";

}

 

 

一、普通消息:

1.創建普通隊列:

/**
     * 創建一個發送字符串的普通消息
     * 參數1 name :隊列名
     * 參數2 durable :是否持久化
     * 參數3 exclusive :僅創建者可以使用的私有隊列,斷開後自動刪除
     * 參數4 autoDelete : 當所有消費客戶端連接斷開後,是否自動刪除隊列
     * @return
     */
    @Bean
    public Queue testQueue(){

        return new Queue(RabbitConstant.TEST_QUEUE,true,false,false);
    }
RabbitConstant.TEST_QUEUE:隊列名稱,字符串類型,自己命名

2.創建一個消息的生產者:

新建controller:

引入rabbitmq的操作工具類:

private RabbitTemplate rabbitTemplate;

    private TXMessage txMessage;

    @Autowired
    public  TestController(RabbitTemplate rabbitTemplate, TXMessage txMessage){
        this.rabbitTemplate = rabbitTemplate;
        this.txMessage = txMessage;
    }
RabbitTemplate:操作rabbitmq的工具類。
TXMessage:確認消息所需要的,這裏可以忽略。

發送消息:

/**
     * 發送普通消息隊列,參數爲字符串
     */
    @GetMapping(value = "sendTestQueue")
    public String sendTestQueue() {

        rabbitTemplate.convertAndSend(RabbitConstant.TEST_QUEUE,"hello-bug");
        log.info("發送參數爲字符串的普通消息完成!");

        return "Success!!!!";
    }

3.創建消費者:

/**
     * 接收普通消息隊列,參數爲字符串
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE)
    public void testQueue(String content){

        log.info("已經接收到消息,參數:{}",content);
    }
@RabbitListener:此註解就是用於監聽mq上是否有生產者生產消息。
queues:制定隊列的名稱。

到此,普通的消息就創建完成了

二、廣播訂閱消息
廣播訂閱消息分爲三種:
1.direct:通過路由key將消息分發到綁定此交換機上的隊列。
2.fanout:發送綁定到交換機上的所有隊列。
3.topic:匹配模式,將消息分發到匹配規則的隊列上。

第一種:direct:

新建兩個普通的隊列:
 

 /**
     * 需要綁定到交換機(direct)上的普通隊列
     * @return
     */
    @Bean
    public Queue testQueuebindDircet1(){

        return new Queue(RabbitConstant.TEST_QUEUE_BIND_DIRECT1,true,false,false);
    }
    /**
     * 需要綁定到交換機(direct)上的普通隊列
     * @return
     */
    @Bean
    public Queue testQueuebindDircet2(){

        return new Queue(RabbitConstant.TEST_QUEUE_BIND_DIRECT2,true,false,false);
    }

新建交換機:
 

/**
     * 訂閱模式----dircet
     *參數1 name :交互器名
     * 參數2 durable :是否持久化
     * 參數3 autoDelete :當所有消費客戶端連接斷開後,是否自動刪除隊列
     * @return
     */
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(RabbitConstant.EXCHANGE_DIRECT,true,false);
    }

將隊列通過路由綁定到交換機上:
 

/**
     * 將普通隊列綁定到交換機(direct)上
     * @return
     */
    @Bean
    public Binding binding1() {
        //鏈式寫法: 用指定的路由鍵將隊列綁定到交換機
        return BindingBuilder.bind(testQueuebindDircet1()).to(directExchange()).with(RabbitConstant.DIRECT_EXCHANGE_ROUTING_KEY);
    }

    /**
     * 將普通隊列綁定到交換機(direct)上
     * @return
     */
    @Bean
    public Binding binding2() {
        //鏈式寫法: 用指定的路由鍵將隊列綁定到交換機
        return BindingBuilder.bind(testQueuebindDircet2()).to(directExchange()).with(RabbitConstant.DIRECT_EXCHANGE_ROUTING_KEY);
    }

現在來創建生產者和消費者:
生產者:
 

/**
     * 發送訂閱消息(direct)
     */
    @GetMapping(value = "sendDirect")
    public String sendDirect() {
        String content = "這是一條訂閱消息(direct)";
        rabbitTemplate.convertAndSend(RabbitConstant.EXCHANGE_DIRECT,RabbitConstant.DIRECT_EXCHANGE_ROUTING_KEY,content);
        log.info("發送路由消息(direct)完成!");

        return "Success!!!!";
    }

消費者:
 

/**
     *接收訂閱消息的隊列1
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_BIND_DIRECT1)
    public void test1(String content){

        log.info("這裏是訂閱隊列1,已經接收到消息,參數:{}",content);
    }

    /**
     *接收訂閱消息的隊列2
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_BIND_DIRECT2)
    public void test2(String content){

        log.info("這裏是訂閱隊列2,已經接收到消息,參數:{}",content);
    }

第二種:Fanout
新建兩個普通隊列:
 

/**
     * 創建普通的消息隊列1(用戶綁定到交換機Fanout上)
     * @return
     */
    @Bean
    public Queue testQueuetoFanout1(){

        return new Queue(RabbitConstant.TEST_QUEUE_TO_FANOUT1,true,false,false);
    }

    /**
     * 創建普通的消息隊列2(用戶綁定到交換機Fanout上)
     * @return
     */
    @Bean
    public Queue testQueuetoFanout2(){

        return new Queue(RabbitConstant.TEST_QUEUE_TO_FANOUT2,true,false,false);
    }

新建交換機:
 

/**
     * 交換機(fanout)
     * @return
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(RabbitConstant.FANOUT_EXCHANGE,true,false);
    }

將兩個隊列綁定到此交換機上,注意,不需要路由key:
 

/**
     * 將普通隊列1綁定到叫環境(direct)上
     * @return
     */
    @Bean
    public Binding bindToFanout1() {
        //鏈式寫法: 用指定的路由鍵將隊列綁定到交換機
        return BindingBuilder.bind(testQueuetoFanout1()).to(fanoutExchange());
    }

    /**
     * 將普通隊列2綁定到叫環境(direct)上
     * @return
     */
    @Bean
    public Binding bindToFanout2() {
        //鏈式寫法: 用指定的路由鍵將隊列綁定到交換機
        return BindingBuilder.bind(testQueuetoFanout2()).to(fanoutExchange());
    }

生產者:
 

 /**
     * 發送訂閱消息(fanout)
     */
    @GetMapping(value = "sendFanout")
    public String sendFanout() {
        String content = "這是一條訂閱消息(fanout)";
        rabbitTemplate.convertAndSend(RabbitConstant.FANOUT_EXCHANGE,"",content);
        log.info("發送路由消息(fanout)完成!");
        return "Success!!!!";
    }

這裏需要注意一點:

這裏的路由key必須要制定爲空字符串,如果不指定,消費者將收不到消息

消費者:
 

/**
     *接收訂閱消息的隊列1
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_TO_FANOUT1)
    public void test1(String content){

        log.info("這裏是訂閱隊列1,已經接收到消息,參數:{}",content);
    }

    /**
     *接收訂閱消息的隊列2
     */
    @RabbitListener(queues = RabbitConstant.TEST_QUEUE_TO_FANOUT2)
    public void test2(String content){

        log.info("這裏是訂閱隊列2,已經接收到消息,參數:{}",content);
    }

好了,下面就是第三種:topic,根據規則匹配:
新建一個普通隊列:
 

/**
     * 創建普通的消息隊列1(用戶綁定到交換機topic上)
     * @return
     */
    @Bean
    public Queue testQueuetoTopic1(){

        return new Queue(RabbitConstant.TEST_QUEUE_TO_TOPIC1,true,false,false);
    }

 

創建交換機:
 

 /**
     * 交換機(topic)
     * @return
     */
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(RabbitConstant.TOPIC_EXCHANGE,true,false);
    }

最後將隊列綁定到交換機上:
 

/**
     * 將普通隊列1綁定到叫環境(Topic)上
     * @return
     */
    @Bean
    public Binding bindingTopic1(@Qualifier("testQueuetoTopic1")Queue queueMessages,TopicExchange exchange){
        return BindingBuilder.bind(queueMessages).to(exchange).with(RabbitConstant.TOPIC_EXCHANGE_ROUTING_KEY);
    }

請看路由key的格式居然是:".#",這裏的意思就是隻要發送topic開頭的隊列,都會、被此路由分發,需要注意一點,這裏的“#”可以用“*”代替。

三種廣播模式的消息介紹完成之後我在介紹一種消息模式:消息的確認機制。

什麼是消息確認機制?

顧名思義,就是消息的發送成功與否、消息是否成功消費都需要一個確認。假如說有這麼一個需求,有兩個微服務:A(訂單服服務)B(庫存服務),當用戶產生一條訂單的時候,庫存也應該相應的減一,如果你正好用的是mq來對兩個服務解耦,那麼有可能會出現這麼一個問題,當A服務的訂單已經生成,然後去發送消息告訴B服務,那如果再發送消息的時候,mq突然掛了,那就代表着消息不會被掛在到mq上,B服務的減庫存也不會發生,這種情況是有可能的,所以mq做出了一種消息的確認機制,就是再發送消息的會有一個回調,告訴消息生產方消息投遞是成功了還是失敗了,消費方也有着同樣的一個機制,要告訴mq這個消息是否被消費了,這就是mq的消息確認機制,如何實現呢?這部分我再源碼裏面有些,大家可以下載源碼直接查看。
源碼地址:https://github.com/361426201/springboot/tree/master/springboot-rabitmq

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章