RabbitMQ 主题模式之Topic交换机

一、Topic交换机

主题模式需要用到Topic类型的交换机

Topic交换机路由匹配规则:

* :精确匹配一个单词,必须要有值

# :匹配0个或者多个单词

举例:
在这里插入图片描述

如上图的主题模式中,Q1队列绑定*.orange.*路由键,Q2绑定*.orange.#路由键

1、如果生产者发送路由为one.orange.two的消息,则C1、C2都可以收到消息

2、如果生产者发送路由为orange.one的消息,则都不能收到消息

3、如果生产者发送路由为one.orange的消息,则只有C2可以收到消息

二、实战

新建两个SpringBoot项目(版本号2.3.4.RELEASE):rabbitmq-provider、rabbitmq-consumer

本机启动RabbitMQ Server,本篇采用Docker来启动,大家也可以安装包启动,两种即可,这里不做赘述。

本篇对上述三种不同路由键做测试。

2.1、rabbitmq-consumer

引入RabbitMQ依赖:pom.xml

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

配置文件:application.properties

server.port=9002
server.servlet.context-path=/consumer
spring.application.name=rabbitmq-consumer

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

新建一个常量类:RabbitMqConstant.java

public interface RabbitMqConstant {
    String TOPIC_EXCHANGE_TEST = "topic.exchange.test";
    String TOPIC_QUEUE_TEST1 = "topic.queue.test1";
    String TOPIC_QUEUE_TEST2 = "topic.queue.test2";
    String TOPIC_ROUTINGKEY_TEST1 = "*.orange.*";
    String TOPIC_ROUTINGKEY_TEST2 = "*.orange.#";
}

写一个监听类,在本类中监听两个队列 topic.queue.test1、topic.queue.test2

@Component
@Slf4j
public class TopicReceiver {

    @RabbitListener(queues = RabbitMqConstant.TOPIC_QUEUE_TEST1)
    public void process1(Message message){
        log.error("process1 receive msg: " + new String(message.getBody()));
    }

    @RabbitListener(queues = RabbitMqConstant.TOPIC_QUEUE_TEST2)
    public void process2(Message message){
        log.error("process2 receive msg: " + new String(message.getBody()));
    }
}
2.2、rabbitmq-provider

引入RabbitMQ依赖:pom.xml

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

配置文件:application.properties

server.port=9001
server.servlet.context-path=/provider
spring.application.name=rabbitmq-provider

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

RabbitMQ配置类:TopicRabbitConfig.java

@Configuration
public class TopicRabbitConfig {

    @Bean
    public TopicExchange topicExchangeTest(){
        /**
         * 创建一个主题型交换机
         * 名字: topic.exchange.test
         * durable(是否持久化): true
         * autoDelete(是否自动删除,当没有生产者或者消费者使用此队列时,该队列会自动删除): false
         */
        return new TopicExchange(RabbitMqConstant.TOPIC_EXCHANGE_TEST,true,false);
    }

    @Bean
    public Queue topicQueueTest1(){
        /**
         * 创建一个队列
         * 名字: topic.queue.test
         * durable(是否持久化): true
         * exclusive(默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable)
         * autoDelete: false
         */
        return new Queue(RabbitMqConstant.TOPIC_QUEUE_TEST1, true, false, false);
    }

    @Bean
    public Queue topicQueueTest2(){
        /**
         * 创建一个队列
         * 名字: topic.queue.test
         * durable(是否持久化): true
         * exclusive(默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable)
         * autoDelete: false
         */
        return new Queue(RabbitMqConstant.TOPIC_QUEUE_TEST2, true, false, false);
    }

    @Bean
    Binding bindingTopic1(){
        return BindingBuilder.bind(topicQueueTest1()).to(topicExchangeTest()).with(RabbitMqConstant.TOPIC_ROUTINGKEY_TEST1);
    }

    @Bean
    Binding bindingTopic2(){
        return BindingBuilder.bind(topicQueueTest2()).to(topicExchangeTest()).with(RabbitMqConstant.TOPIC_ROUTINGKEY_TEST2);
    }

新建一个常量类:RabbitMqConstant.java

public interface RabbitMqConstant {
    String TOPIC_EXCHANGE_TEST = "topic.exchange.test";
    String TOPIC_QUEUE_TEST1 = "topic.queue.test1";
    String TOPIC_QUEUE_TEST2 = "topic.queue.test2";
    String TOPIC_ROUTINGKEY_TEST1 = "*.orange.*";
    String TOPIC_ROUTINGKEY_TEST2 = "*.orange.#";
}

为了测试发送Message,这里写一个工具Controller:SendMessageController.java

1、首先来测试第一种情况:RoutingKey=“one.orange.two”

@RestController
public class SendMessageController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/sendMessageTopic")
    public String sendMessageTopic(String msg){
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend(RabbitMqConstant.TOPIC_EXCHANGE_TEST, "one.orange.two", msg + "#" + i);
        }
        return "success";
    }
}

启动rabbitmq-provider

通过Postman来调用我们的Controller接口
在这里插入图片描述
调用成功后,去RabbitMQ管理页面查看,可以看到两个队列中都存在这10条消息。

注意:当rabbitmq-provider启动后,在RabbitMQ管理页面是看不到这两个队列,只有在扔消息时,RabbitMQ才会去创建这两个队列。
在这里插入图片描述

启动rabbitmq-consumer,会看到控制台日志打印:
在这里插入图片描述
2、测试第二种情况:RoutingKey=“orange.one”
停止启动rabbitmq-consumer(为了便于观察消息队列管理页面中的消息数量)

@RestController
public class SendMessageController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/sendMessageTopic")
    public String sendMessageTopic(String msg){
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend(RabbitMqConstant.TOPIC_EXCHANGE_TEST, "orange.two", msg + "#" + i);
        }
        return "success";
    }
}

启动rabbitmq-provider

通过Postman来调用我们的Controller接口

调用成功后,去RabbitMQ管理页面查看,可以看到两个队列中都不存在这10条消息。
在这里插入图片描述
3、测试第三种情况:RoutingKey=“one.orange”

@RestController
public class SendMessageController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/sendMessageTopic")
    public String sendMessageTopic(String msg){
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend(RabbitMqConstant.TOPIC_EXCHANGE_TEST, "one.orange", msg + "#" + i);
        }
        return "success";
    }
}

启动rabbitmq-provider

通过Postman来调用我们的Controller接口

调用成功后,去RabbitMQ管理页面查看,可以看到只有在queue2队列中都存在这10条消息。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值