文章目录
本文参考:
尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmq
RabbitMQ 详解
Centos7环境安装Erlang、RabbitMQ详细过程(配图)
一、通配符模式原理
通配符模式(Topics)是在路由模式的基础上,给队列绑定带通配符的路由关键字,只要消息的 RoutingKey 能实现通配符匹配,就会将消息转发到该队列。通配符模式比路由模式更灵活,通配符模式使用** topic 交换机**。 能按照通配符规则将消息发送给指定队列。
发送到类型是 topic 交换机的消息的 routingkey 不能随意写,必须满足一定的要求,它必须是一个词列表,以点号分隔开。这些词可以是任意的。
比如说:“stock.usd.nyse”,“nyse.vmw”,“quick.orange.rabbit” 这种类型的。但这个词列表最多不能超过 255 个字节。
通配符规则如下:
- 队列设置 RoutingKey 时,“#” 可以匹配任意多个单词,“*” 可以匹配任意一个单词。
- 消息设置 RoutingKey 时,RoutingKey 由多个单词构成,中间以 “.” 分割开。
二、通配符模式实战
上图绑定关系如下:
- Q1–>绑定的是中间带orange的3个单词的字符串(.orange.)。
- Q2–>绑定的是最后一个单词是rabbit的3个单词的字符串(..rabbit)以及第一个单词是lazy的多个单词的字符串(lazy.#)。
1、消费者代码
消费者01代码如下:
/**
* Description: 通配符模式消费者01
*/publicclassReceiveLogsTopic01{privatestaticfinalString EXCHANGE_NAME ="topic_logs";publicstaticvoidmain(String[] argv)throwsException{Channel channel =RabbitUtils.getChannel();
channel.exchangeDeclare(EXCHANGE_NAME,"topic");//声明 Q1 队列与绑定关系 String queueName="Q1";
channel.queueDeclare(queueName,false,false,false,null);//绑定关系并指定routingkey
channel.queueBind(queueName, EXCHANGE_NAME,"*.orange.*");System.out.println("等待接收消息.....");//接收消息
channel.basicConsume(queueName,true,newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throwsIOException{String message =newString(body,"UTF-8");System.out.println("接收队列:"+ queueName +"绑定键:"+ envelope.getRoutingKey()+",消息:"+ message);}});}}
消费者02代码如下:
/**
* Description: 通配符模式消费者02
*/publicclassReceiveLogsTopic02{privatestaticfinalString EXCHANGE_NAME ="topic_logs";publicstaticvoidmain(String[] argv)throwsException{Channel channel =RabbitUtils.getChannel();
channel.exchangeDeclare(EXCHANGE_NAME,"topic");//声明 Q2 队列与绑定关系 String queueName="Q2";
channel.queueDeclare(queueName,false,false,false,null);//绑定关系并指定routingkey
channel.queueBind(queueName, EXCHANGE_NAME,"*.*.rabbit");
channel.queueBind(queueName, EXCHANGE_NAME,"lazy.#");System.out.println("等待接收消息.....");//接收消息
channel.basicConsume(queueName,true,newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body)throwsIOException{String message =newString(body,"UTF-8");System.out.println("接收队列:"+ queueName +"绑定键:"+ envelope.getRoutingKey()+",消息:"+ message);}});}}
2、生产者代码
/**
* Description: 通配符模式消费者02
*/publicclassEmitLogTopic{privatestaticfinalString EXCHANGE_NAME ="topic_logs";publicstaticvoidmain(String[] argv)throwsException{Channel channel =RabbitUtils.getChannel();Map<String,String> bindingKeyMap =newHashMap<>();
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 routingKey = bindingKeyEntry.getKey();String message = bindingKeyEntry.getValue();
channel.basicPublish(EXCHANGE_NAME,routingKey,null, message.getBytes("UTF-8"));System.out.println("生产者发出消息"+ message);}}}
3、查看运行结果
将两个消费者和一个生产者分别启动:
根据匹配规则,以及预先设置好的预期打印结果可以看到,Q1只接收了应该被Q1接收的三条消息,其他的没有接收,同理Q2也之接收了自己匹配规则之内的。并且可以发现当一条消息的routingkey既能够匹配Q1规则又能够匹配Q2规则时,Q1和Q2都能接收到该条消息。
版权归原作者 Scr1Pt0908 所有, 如有侵权,请联系我们删除。