RabbitMQ三之主题Topic

一、概念

发送到类型是 topic 交换机的消息的 routing_key 不能随意写,必须满足一定的要求,它必须是一个单词列表,以点号分隔开。这些单词可以是任意单词,比如说: "stock.usd.nyse", "nyse.vmw","quick.orange.rabbit".这种类型的。当然这个单词列表最多不能超过 255 个字节。


在这个规则列表中,其中有两个替换符是大家需要注意的
*(星号)可以代替一个单词
#(井号)可以替代零个或多个单词

 上图是一个队列绑定关系图,我们来看看他们之间数据接收情况是怎么样的

quick.orange.rabbit                 被队列 Q1Q2 接收到
lazy.orange.elephant               被队列 Q1Q2 接收到
quick.orange.fox                      被队列 Q1 接收到
lazy.brown.fox                          被队列 Q2 接收到
lazy.pink.rabbit                         虽然满足两个绑定但只被队列 Q2 接收一次
quick.brown.fox                        不匹配任何绑定不会被任何队列接收到会被丢弃
quick.orange.male.rabbit         是四个单词不匹配任何绑定会被丢弃
lazy.orange.male.rabbit            是四个单词但匹配 Q2

二、实例

1.消费者1

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.zym.rabbitmq.utils.RabbitMqUtils;

public class ReceiveLogsTopic01 {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();

        // 声明交换机,第一个参数:交换机名称  第二个参数:交换机类型
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        // 队列名称
        String queueName = "Q1";
        // 创建队列
        channel.queueDeclare(queueName,false,false,false,null);
        // 把队列绑定到交换机上  第一参数:队列名称  第二参数: 交换机名称  第三参数:绑定的key
        channel.queueBind(queueName,EXCHANGE_NAME,"*.orange.*");
        System.out.println("等待接收消息....");

        // 推送的消息如何消费的接口回调
        DeliverCallback deliverCallback = (consumerTag, delivery) ->{
            String message = new String(delivery.getBody());
            System.out.println("接收队列:"+queueName+"绑定的key:"+delivery.getEnvelope().getRoutingKey()+"消息"+message);
        };

        // 取消消费的一个回调接口
        CancelCallback cancelCallback = (consumerTag)->{
            System.out.println("消息消费被中断");
        };

        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }

}

2.消费者2

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.zym.rabbitmq.utils.RabbitMqUtils;

public class ReceiveLogsTopic02 {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();

        // 声明交换机,第一个参数:交换机名称  第二个参数:交换机类型
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        // 队列名称
        String queueName = "Q2";
        // 创建队列
        channel.queueDeclare(queueName,false,false,false,null);
        // 把队列绑定到交换机上  第一参数:队列名称  第二参数: 交换机名称  第三参数:绑定的key
        channel.queueBind(queueName,EXCHANGE_NAME,"*.*.rabbit");
        channel.queueBind(queueName,EXCHANGE_NAME,"lazy.#");
        System.out.println("等待接收消息....");

        // 推送的消息如何消费的接口回调
        DeliverCallback deliverCallback = (consumerTag, delivery) ->{
            String message = new String(delivery.getBody());
            System.out.println("接收队列:"+queueName+",绑定的key:"+delivery.getEnvelope().getRoutingKey()+",消息"+message);
        };

        // 取消消费的一个回调接口
        CancelCallback cancelCallback = (consumerTag)->{
            System.out.println("消息消费被中断");
        };

        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}

3.生产者

import com.rabbitmq.client.Channel;
import com.zym.rabbitmq.utils.RabbitMqUtils;

import java.util.HashMap;
import java.util.Map;

public class EmitLogTopic {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] argv) throws Exception {
        try (Channel channel = RabbitMqUtils.getChannel()) {
            channel.exchangeDeclare(EXCHANGE_NAME, "topic");
            /**
             * Q1-->绑定的是
             * 中间带 orange 带 3 个单词的字符串(*.orange.*)
             * Q2-->绑定的是
             * 最后一个单词是 rabbit 的 3 个单词(*.*.rabbit)
             * 第一个单词是 lazy 的多个单词(lazy.#)
             *
             */
            Map<String, String> bindingKeyMap = new HashMap<>();
            bindingKeyMap.put("quick.orange.rabbit", "被队列 Q1Q2 接收到");
            bindingKeyMap.put("lazy.orange.elephant", "被队列 Q1Q2 接收到");
            bindingKeyMap.put("quick.orange.fox", "被队列 Q1 接收到");
            bindingKeyMap.put("lazy.brown.fox", "被队列 Q2 接收到");
            bindingKeyMap.put("lazy.pink.rabbit", "虽然满足两个绑定但只被队列 Q2 接收一次");
            bindingKeyMap.put("quick.brown.fox", "不匹配任何绑定不会被任何队列接收到会被丢弃");
            bindingKeyMap.put("quick.orange.male.rabbit", "是四个单词不匹配任何绑定会被丢弃");
            bindingKeyMap.put("lazy.orange.male.rabbit", "是四个单词但匹配 Q2");
            for (Map.Entry<String, String> bindingKeyEntry : bindingKeyMap.entrySet()) {
                String bindingKey = bindingKeyEntry.getKey();
                String message = bindingKeyEntry.getValue();
                channel.basicPublish(EXCHANGE_NAME, bindingKey, null,message.getBytes("UTF-8"));
                System.out.println("生产者发出消息" + message);
            }
        }
    }

}

4.结果

消费者1

消费者2

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值