SpringBoot中RabbitMQ動態(tài)創(chuàng)建隊列以及綁定關(guān)系(AmqpAdmin)

SpringBoot中一般我們創(chuàng)建RabbitMQ隊列以及綁定關(guān)系枫弟,是通過@Bean的方式萧恕,但是RabbitMQ提供了AmqpAdmin對象玄柏,可以在代碼中聲明隊列以及綁定關(guān)系八拱。

讀取配置文件的RabbitMQ的組件信息柱恤,然后動態(tài)的去創(chuàng)建關(guān)系。

配置文件格式:

/**
 * RabbitMq的隊列拷况,交互機作煌,綁定關(guān)系的對象
 *
 */
@Data
public class RabbitModuleInfo {

    /**
     * 路由主鍵
     */
    private String routingKey;

    /**
     * 隊列信息
     */
    private Queue queue;

    /**
     * 交換機信息
     */
    private Exchange exchange;

    /**
     * 交換機的詳細配置
     */
    @Data
    public static class Exchange {

        /**
         * 交互機名稱
         */
        private String name;

        /**
         * 交互機類型。
         * 默認:直連型號
         */
        private ExchangeTypeEnum type = ExchangeTypeEnum.DIRECT;

        /**
         * 是否持久化
         * 默認true:當(dāng)RabbitMq重啟時赚瘦,消息不丟失
         */
        private boolean durable = true;

        /**
         * 當(dāng)所有綁定隊列都不在使用時粟誓,是否自動 刪除交換器
         * 默認值false:不自動刪除,推薦使用起意。
         */
        private boolean autoDelete = false;

        /**
         * 判斷是否是延遲交互機
         */
        private boolean delayed;

        /**
         * 交互機的額外參數(shù)
         */
        private java.util.Map<String, Object> arguments;

    }


    /**
     * 隊列的詳細信息
     * 提供默認的配置參數(shù)
     */
    @Data
    public static class Queue {

        /**
         * 隊列名
         * 必填
         */
        private String name;

        /**
         * 是否持久化
         * 默認true:當(dāng)RabbitMq重啟時鹰服,消息不丟失
         */
        private boolean durable = true;

        /**
         * 是否具有排他性
         * 默認false:可以多個消息者消費同一個隊列
         */
        private boolean exclusive = false;

        /**
         * 當(dāng)消費者客戶端均斷開連接,是否自動刪除隊列
         * 默認值false:不自動刪除,推薦使用悲酷,避免消費者斷開后套菜,隊列中丟棄消息
         */
        private boolean autoDelete = false;

        /**
         * 需要綁定的死信隊列的交換機名稱
         */
        private String deadExchangeName;

        /**
         * 需要綁定的死信隊列的路由key的名稱
         */
        private String deadRoutingKey;

        /**
         * 隊列的額外參數(shù)
         */
        private java.util.Map<String, Object> arguments;

    }


}
@Data
@ConfigurationProperties(prefix = "my.rabbit")
public class SealRabbitProperty {


    /**
     * 組件信息(讀取配置文件,自動創(chuàng)建隊列信息)
     */
    private List<RabbitModuleInfo> moduleInfos;

}

配置文件:

my:
  rabbit:
    module-infos:
      # ocr隊列
      - routing-key:my.routing.xx
        queue:
          name:my.queue.xx
        exchange:
          name: my.exchage.xx
      - routing-key: my.routing.yy
        queue:
          name:my.queue.yy
        exchange:
          name: my.exchage.yy
          type: FANOUT

聲明操作類(容器中單例bean創(chuàng)建完畢设易,執(zhí)行回調(diào)方法):

    @Bean
    @ConditionalOnMissingBean
    public DeclareRabbitModule declareRabbitModule(RegisterRabbitModule rabbitModule, SealRabbitProperty sealRabbitProperty) {
        return new DeclareRabbitModule(rabbitModule, sealRabbitProperty);
    }
@Slf4j
public class RegisterRabbitModule {

    private AmqpAdmin amqpAdmin;

    public void setAmqpAdmin(AmqpAdmin amqpAdmin) {
        this.amqpAdmin = amqpAdmin;
    }


    /**
     * 注冊RabbitMq的組件信息
     *
     * @param queue    隊列對象
     * @param exchange 交換機對象
     * @param binding  隊列與交換機綁定關(guān)系對象
     */
    public void registerModule(Queue queue, Exchange exchange, Binding binding) {
        amqpAdmin.declareQueue(queue);
        amqpAdmin.declareExchange(exchange);
        amqpAdmin.declareBinding(binding);
    }


}

@Slf4j
public class DeclareRabbitModule implements SmartInitializingSingleton {

    /**
     * 死信隊列 交換機標(biāo)識符
     */
    public static final String DEAD_LETTER_QUEUE_KEY = "x-dead-letter-exchange";
    /**
     * 死信隊列交換機綁定鍵標(biāo)識符
     */
    public static final String DEAD_LETTER_ROUTING_KEY = "x-dead-letter-routing-key";


    private AmqpAdmin amqpAdmin;

    private SealRabbitProperty sealRabbitProperty;


    public DeclareRabbitModule(AmqpAdmin amqpAdmin, SealRabbitProperty sealRabbitProperty) {
        this.amqpAdmin = amqpAdmin;
        this.sealRabbitProperty = sealRabbitProperty;
    }

    @Override
    public void afterSingletonsInstantiated() {
        log.info("動態(tài)創(chuàng)建MQ配置信息...");
        declareModule();
    }

    private void declareModule() {
        //獲取組件信息
        List<RabbitModuleInfo> moduleInfos = sealRabbitProperty.getModuleInfos();
        if (CollectionUtils.isEmpty(moduleInfos)) {
            log.warn("配置文件中不含有組件信息笼踩,不進行注冊!");
            return;
        }
        //注冊組件信息
        for (RabbitModuleInfo moduleInfo : moduleInfos) {
            //數(shù)據(jù)校驗
            declareValidate(moduleInfo);
            //獲取隊列
            Queue queue = tranSealQueue(moduleInfo.getQueue());
            //獲取交換機
            Exchange exchange = tranSealExchange(moduleInfo.getExchange());
            //綁定關(guān)系
            Binding binding = new Binding(queue.getName(), Binding.DestinationType.QUEUE,
                    exchange.getName(), moduleInfo.getRoutingKey(), null);
            //創(chuàng)建隊列
            amqpAdmin.declareQueue(queue);
            amqpAdmin.declareExchange(exchange);
            amqpAdmin.declareBinding(binding);
        }
    }


    /**
     * 聲明模塊數(shù)據(jù)校驗
     *
     * @param moduleInfo 配置文件的模塊信息
     */
    public void declareValidate(RabbitModuleInfo moduleInfo) {
        //判斷關(guān)鍵參數(shù)是否存在且合法
        if (moduleInfo.getRoutingKey() == null) {
            throw new RabbitDeclareModuleException("RoutingKey 不存在亡嫌!");
        }

        if (moduleInfo.getExchange() == null) {
            throw new RabbitDeclareModuleException(String.format("my-rabbit的配置文件中,routingKey:[%s]未配置exchange掘而!", moduleInfo.getRoutingKey()));
        }
        if (moduleInfo.getExchange().getName() == null) {
            throw new RabbitDeclareModuleException(String.format("my-rabbit的配置文件中挟冠,routingKey:[%s]未配置exchange的name屬性!", moduleInfo.getRoutingKey()));
        }
        if (moduleInfo.getQueue() == null) {
            throw new RabbitDeclareModuleException(String.format("my-rabbit的配置文件中袍睡,routingKey:[%s]未配置queue知染!", moduleInfo.getRoutingKey()));
        }
        if (moduleInfo.getQueue().getName() == null) {
            throw new RabbitDeclareModuleException(String.format("my-rabbit的配置文件中,routingKey:[%s]未配置queue的name屬性斑胜!", moduleInfo.getRoutingKey()));
        }
    }


    /**
     * 隊列的對象轉(zhuǎn)換
     *
     * @param queue 自定義的隊列信息
     * @return RabbitMq的Queue對象
     */
    private Queue tranSealQueue(RabbitModuleInfo.Queue queue) {
        Map<String, Object> arguments = queue.getArguments();
        //判斷是否需要綁定死信隊列
        if (queue.getDeadExchangeName() != null && queue.getDeadRoutingKey() != null) {
            //設(shè)置響應(yīng)參數(shù)
            if (queue.getArguments() == null) {
                arguments = new HashMap<>(2);
            }
            arguments.put(DEAD_LETTER_QUEUE_KEY, queue.getDeadExchangeName());
            arguments.put(DEAD_LETTER_ROUTING_KEY, queue.getDeadRoutingKey());
        }
        return new Queue(queue.getName(), queue.isDurable(), queue.isExclusive(), queue.isAutoDelete(), arguments);
    }


    /**
     * 將配置信息轉(zhuǎn)換交換機信息
     *
     * @param exchangeInfo 自定義交換機信息
     * @return RabbitMq的Exchange的信息
     */
    private Exchange tranSealExchange(RabbitModuleInfo.Exchange exchangeInfo) {
        AbstractExchange exchange = null;
        //判斷類型
        switch (exchangeInfo.getType()) {
            //直連模式
            case DIRECT:
                exchange = new DirectExchange(exchangeInfo.getName(), exchangeInfo.isDurable(), exchangeInfo.isAutoDelete(), exchangeInfo.getArguments());
                break;
            //廣播模式:
            case FANOUT:
                exchange = new FanoutExchange(exchangeInfo.getName(), exchangeInfo.isDurable(), exchangeInfo.isAutoDelete(), exchangeInfo.getArguments());
                break;
            //通配符模式
            case TOPIC:
                exchange = new TopicExchange(exchangeInfo.getName(), exchangeInfo.isDurable(), exchangeInfo.isAutoDelete(), exchangeInfo.getArguments());
                break;
            case HEADERS:
                exchange = new HeadersExchange(exchangeInfo.getName(), exchangeInfo.isDurable(), exchangeInfo.isAutoDelete(), exchangeInfo.getArguments());
                break;
        }
        //設(shè)置延遲隊列
        exchange.setDelayed(exchangeInfo.isDelayed());
        return exchange;
    }

}

在項目啟動后控淡,便會去讀取配置文件的信息,然后去創(chuàng)建RabbitMQ的組件信息止潘,實現(xiàn)了配置集中管理掺炭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市凭戴,隨后出現(xiàn)的幾起案子涧狮,更是在濱河造成了極大的恐慌,老刑警劉巖么夫,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件者冤,死亡現(xiàn)場離奇詭異,居然都是意外死亡档痪,警方通過查閱死者的電腦和手機涉枫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腐螟,“玉大人愿汰,你說我怎么就攤上這事≡舛猓” “怎么了尼桶?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锯仪。 經(jīng)常有香客問我泵督,道長,這世上最難降的妖魔是什么庶喜? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任小腊,我火速辦了婚禮救鲤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秩冈。我一直安慰自己本缠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布入问。 她就那樣靜靜地躺著丹锹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芬失。 梳的紋絲不亂的頭發(fā)上楣黍,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音棱烂,去河邊找鬼租漂。 笑死,一個胖子當(dāng)著我的面吹牛颊糜,可吹牛的內(nèi)容都是我干的哩治。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼衬鱼,長吁一口氣:“原來是場噩夢啊……” “哼业筏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鸟赫,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤驾孔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惯疙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翠勉,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年霉颠,在試婚紗的時候發(fā)現(xiàn)自己被綠了对碌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡蒿偎,死狀恐怖朽们,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诉位,我是刑警寧澤骑脱,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站苍糠,受9級特大地震影響叁丧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一拥娄、第九天 我趴在偏房一處隱蔽的房頂上張望蚊锹。 院中可真熱鬧,春花似錦稚瘾、人聲如沸牡昆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丢烘。三九已至,卻和暖如春些椒,著一層夾襖步出監(jiān)牢的瞬間铅协,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工摊沉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人痒给。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓说墨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親苍柏。 傳聞我的和親對象是個殘疾皇子尼斧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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