4、Rabbitmq交换机topic

本文深入探讨了RabbitMQ中Topic类型的Exchange使用方法,包括如何利用通配符进行灵活的消息路由,从声明交换机、队列绑定到消费者监听及消息发送的全过程。通过实例演示,展示了不同RoutingKey下消息如何被正确地路由到指定队列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Topic类型的Exchange与Direct相比,都是可以根据Routing Key把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key的时候使用通配符!

Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert

通配符规则:

​ #:匹配一个或多个词

​ *:匹配不多不少恰好1个词

举例:

e98798085bda553b488c452fcc4b2e8c89d.jpg

在这个例子中:

​ lazy.#:能够匹配lazy.aa.bb或者 lazy.aa

​ *.orange.*:只能匹配aa.orange.bb

 

1、声明交换机

    /**
     * 1、声明交换机
     */
    @Test
    public void decalreExchange() throws Exception {

        String exchange = "hello_topic";
        // 获取到连接
        Connection connection = ConnectionUtil.getConnection();
        // 获取通道
        Channel channel = connection.createChannel();

        // 声明exchange,指定类型为topic
        channel.exchangeDeclare(exchange, BuiltinExchangeType.TOPIC,true,false,false,new HashMap<>());
    }

运行后,可以看到交换机已创建成功

6022a4a1673e5b66597e3af48641a17f36e.jpg

 

2、声明队列并绑定到交换机

    /**
     * 2、声明队列并绑定到交换机
     */
    @Test
    public void decalreQueueAndBind() throws Exception {

        String exchange = "hello_topic";
        // 获取到连接
        Connection connection = ConnectionUtil.getConnection();
        // 获取通道
        Channel channel = connection.createChannel();

        //将队列hello_topic_c1 绑定到交换机hello_topic上
        String queueName1 = "hello_topic_c1";
        // 声明队列
        channel.queueDeclare(queueName1, true, false, false, null);
        // 绑定队列到交换机
        String routingKey1 = "*.orange.*";
        channel.queueBind(queueName1, exchange, routingKey1,null);

        //将队列hello_topic_c2 绑定到交换机hello_topic上
        String queueName2 = "hello_topic_c2";
        // 声明队列
        channel.queueDeclare(queueName2, false, false, false, null);
        // 绑定队列到交换机
        String routingKey2 = "lazy.#";
        channel.queueBind(queueName2, exchange, routingKey2,null);

    }

运行后可以看到队列创建成功,

7663f585c7054007020f65b43a505d702d4.jpg

点击队列,查看队列信息,可以看到队列c1 和 c2都绑定到了hello_topic交换机上,路由键分别为lazy.#和*.orange.*。当我们发送

lazy.aa、lazy.aa.bb等这种路由键的消息,会被路由到队列c1。

aa.orange.bb、cc.orange.aa 等这种路由键的消息,会被路由到队列c2。

14abcf84dde2eec20d63c022b88ea66c94d.jpg

b52b1f0e65a8cb8bb42bee182b05e6c776f.jpg

定义两个消费者,1个监听队列hello_topic_c1 、1个监听队列hello_topic_c2 并运行。

//消费者1
@Slf4j
public class Consumer1 {

    public static void main(String[] argv) throws Exception {
        String queueName = "hello_topic_c1";
        // 获取到连接
        Connection connection = ConnectionUtil.getConnection();
        // 获取通道
        Channel channel = connection.createChannel();
        // 定义队列的消费者
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                       byte[] body) throws IOException {
                // body 即消息体
                String msg = new String(body);
                log.debug("Consumer1 consume msg:{}",msg);
            }
        };
        // 监听队列,自动返回完成
        channel.basicConsume(queueName, true, consumer);
    }
}

 

// 消费者2
@Slf4j
public class Consumer2 {


    public static void main(String[] argv) throws Exception {
        String queueName = "hello_topic_c2";
        // 获取到连接
        Connection connection = ConnectionUtil.getConnection();
        // 获取通道
        Channel channel = connection.createChannel();
        // 定义队列的消费者
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                       byte[] body) throws IOException {
                // body 即消息体
                String msg = new String(body);
                log.debug("Consumer2 consume msg:{}",msg);
            }
        };
        // 监听队列,自动返回完成
        channel.basicConsume(queueName, true, consumer);
    }
}

 

发送消息:这里发送routing key 符合lazy.#规则的两条消息以及符合*.orange.*规则的两条消息

    /**
     * 生产者发送消息
     * @throws Exception
     */
    @Test
    public void sendMessage() throws Exception {
        String exchange = "hello_topic";
        // 获取到连接
        Connection connection = ConnectionUtil.getConnection();
        // 获取通道
        Channel channel = connection.createChannel();
        // 发布消息到Exchange 指定路由键符合 *.orange.*
        channel.basicPublish(exchange, "aa.orange.bb", null, "Less is more aa.orange.bb".getBytes());
        channel.basicPublish(exchange, "cc.orange.dd", null, "Less is more cc.orange.dd".getBytes());

        // 发布消息到Exchange 指定路由键符合lazy.#
        channel.basicPublish(exchange, "lazy.aa", null, "Less is more lazy.aa".getBytes());
        channel.basicPublish(exchange, "lazy.aa.bb", null, "Less is more lazy.aa.bb".getBytes());

        channel.close();
        connection.close();
    }

 

可以看到消费者都收到了各自的消息:

消费者1:

5022a8f28c0a84c240a463281e1b2d68112.jpg

消费者2:

fe103ea2ddd102fea9a802890558f9c680f.jpg

 

详细源码地址

https://github.com/suzhe2018/rabbitmq-item

a059b8e2d2d6b6f89ee145ad151aecbe506.jpg

转载于:https://my.oschina.net/suzheworld/blog/3002686

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值