SpringBoot整合RabbitMQ系列(二)Exchange的四种类型

Exchange是什么

我们可以将 Exchange 当做一个消息的中转站,所有的消息在发送到指定队列前都要经过这一层中转站。中转站再根据某些规则进行匹配来决定将消息分发到哪些队列中。

Exchange的几种类型

  1. Direct(默认)
    只有当 Routing Key 等于 Binding Key 时,消息才会被路由到队列中。
  2. Fanout
    实现了一种广播机制,将消息发送到所有与这个 Exchange 绑定的队列中。
  3. Topic
    定义了一种匹配规则,同样根据 Routing Key 和 Binding Key 进行模糊匹配,更加灵活。
  4. Headers
    Headers Exchange 会忽略 RoutingKey 而根据消息中的 Headers 和创建绑定关系时指定的 Arguments 来匹配决定路由到哪些 Queue,其性能比较差而且 Direct Exchange 完全可以代替它,所以不建议使用。

Exchange 的创建与绑定

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "队列名"),
            exchange = @Exchange(name = "交换机名称"), key = "Binding Key"))
    public void listen(String msg) {
        log.info("成功消费队列的消息: {}", msg);
    }

以上就是一个通过注解声明队列同时绑定Exchange的一个列子。
如果仅声明一条队列,那么当它被创建时,后台会自动将这个队列绑定到一个名称为空的 Direct Exchange 上,绑定 Routing Key 与队列名称相同。

代码示例

package com.jiangzhe.rabbitmq.chapter2;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Slf4j
@EnableScheduling
@SpringBootApplication
public class Chapter2Application {
    private static final String FANOUT_EXCHANGE_NAME = "amqp.fanout";
    private static final String TOPIC_EXCHANGE_NAME = "amqp.topic";
    private static final String DIRECT_EXCHANGE_NAME = "amqp.direct";

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public static void main(String[] args) {
        SpringApplication.run(Chapter2Application.class, args);
    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "direct"),
            exchange = @Exchange(name = DIRECT_EXCHANGE_NAME), key = "direct.cn"))
    public void listenDirect(String msg, Message message) {
        String consumerQueue = message.getMessageProperties().getConsumerQueue();
        log.info("成功消费队列 {} 的消息: {}", consumerQueue, msg);
    }

    @RabbitListener(bindings = {
            @QueueBinding(value = @Queue(value = "fanoutA"),
                    exchange = @Exchange(type = ExchangeTypes.FANOUT, name = FANOUT_EXCHANGE_NAME)),
            @QueueBinding(value = @Queue(value = "fanoutB"),
                    exchange = @Exchange(type = ExchangeTypes.FANOUT, name = FANOUT_EXCHANGE_NAME)),
            @QueueBinding(value = @Queue(value = "fanoutC"),
                    exchange = @Exchange(type = ExchangeTypes.FANOUT, name = FANOUT_EXCHANGE_NAME))})
    public void listenFanout(String msg, Message message) {
        String consumerQueue = message.getMessageProperties().getConsumerQueue();
        log.info("成功消费队列 {} 的消息: {}", consumerQueue, msg);
    }

    /**
     * 其中*代表匹配任意的一个词,#代表匹配0或多个词
     */
    @RabbitListener(bindings = {
            @QueueBinding(value = @Queue(name = "topicA"),
                    exchange = @Exchange(type = ExchangeTypes.TOPIC, name = TOPIC_EXCHANGE_NAME), key = "topic.cn.#"),
            @QueueBinding(value = @Queue(name = "topicB"),
                    exchange = @Exchange(type = ExchangeTypes.TOPIC, name = TOPIC_EXCHANGE_NAME), key = "topic.com.*"),
            @QueueBinding(value = @Queue(name = "topicC"),
                    exchange = @Exchange(type = ExchangeTypes.TOPIC, name = TOPIC_EXCHANGE_NAME), key = "topic.#"),
    })
    public void listenTopic(String msg, Message message) {
        String consumerQueue = message.getMessageProperties().getConsumerQueue();
        log.info("成功消费队列 {} 的消息: {}", consumerQueue, msg);
    }

    @Scheduled(initialDelay = 2000, fixedRate = 1000000)
    public void send() throws InterruptedException {
        log.info("----------------------------");
        log.info("direct");
        rabbitTemplate.convertAndSend(DIRECT_EXCHANGE_NAME, "direct.cn", "hello");
        Thread.sleep(1000);
        log.info("----------------------------");
        log.info("fanout");
        rabbitTemplate.convertAndSend(FANOUT_EXCHANGE_NAME, "这个值无效", "hello");
        Thread.sleep(1000);
        log.info("----------------------------");
        log.info("to topicC and topicC");
        rabbitTemplate.convertAndSend(TOPIC_EXCHANGE_NAME, "topic.com.a", "hello");
        Thread.sleep(1000);
        log.info("----------------------------");
        log.info("to topicA and topicC");
        rabbitTemplate.convertAndSend(TOPIC_EXCHANGE_NAME, "topic.cn", "hello");
    }

}

输出结果

2019-11-02 12:54:09.775  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : ----------------------------
2019-11-02 12:54:09.775  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : direct
2019-11-02 12:54:09.849  INFO 2756 --- [ntContainer#2-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 direct 的消息: hello
2019-11-02 12:54:10.809  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : ----------------------------
2019-11-02 12:54:10.809  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : fanout
2019-11-02 12:54:10.839  INFO 2756 --- [ntContainer#1-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 fanoutA 的消息: hello
2019-11-02 12:54:10.839  INFO 2756 --- [ntContainer#1-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 fanoutB 的消息: hello
2019-11-02 12:54:10.839  INFO 2756 --- [ntContainer#1-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 fanoutC 的消息: hello
2019-11-02 12:54:11.809  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : ----------------------------
2019-11-02 12:54:11.809  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : to topicC and topicC
2019-11-02 12:54:11.838  INFO 2756 --- [ntContainer#0-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 topicB 的消息: hello
2019-11-02 12:54:11.838  INFO 2756 --- [ntContainer#0-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 topicC 的消息: hello
2019-11-02 12:54:12.810  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : ----------------------------
2019-11-02 12:54:12.810  INFO 2756 --- [   scheduling-1] c.j.r.chapter2.Chapter2Application       : to topicA and topicC
2019-11-02 12:54:12.840  INFO 2756 --- [ntContainer#0-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 topicC 的消息: hello
2019-11-02 12:54:12.840  INFO 2756 --- [ntContainer#0-1] c.j.r.chapter2.Chapter2Application       : 成功消费队列 topicA 的消息: hello
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容