前言

上篇我们学习了rabbitmq的作用以及直连交换机的代码实现,这篇我们继续看如何用代码实现扇形交换机和主题交换机

一、扇形交换机

  1.生产者

  

/**
* 生产者
*/
public class LogProducer {
//交换机名称
public final static String EXCHANGE_NAME = "logs"; public static void main(String[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME,"fanout"); for (int i = 0; i < 5;i++){
String message = "Hello Rabbit " + i;
channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes());
System.out.println("EmitLog send message " + message);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
channel.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
} }
}
}

  2.消费者

  Consumer1

/**
* 消费者
*/
public class Consumer1 {
public final static String EXCHANGE_NAME = "logs"; public static void main(String[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
channel = connection.createChannel();
String queueName = channel.queueDeclare().getQueue();
//声明一个交换机,发布模式为fanout-扇形
channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
//将队列和交换机绑定起来,因为扇形交换机和路由键无关,所以这里路由键设为空字符串即可
channel.queueBind(queueName,EXCHANGE_NAME,""); QueueingConsumer consumer = new QueueingConsumer(channel);
//当连接断开时,队列会自动被删除
channel.basicConsume(queueName,true,consumer);
System.out.println("ReceiveLogTopic1 Waitting for message");
while (true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("ReceiveLogTopic1 receives message " + message);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

  Cosumer2

  

/**
* 消费者2
*/
public class Consumer2 {
public final static String EXCHANGE_NAME = "logs"; public static void main(String[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
channel = connection.createChannel();
String queueName = channel.queueDeclare().getQueue();
//声明一个交换机,发布模式为fanout-扇形
channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
//将队列和交换机绑定起来,因为扇形交换机和路由键无关,所以这里路由键设为空字符串即可
channel.queueBind(queueName,EXCHANGE_NAME,""); QueueingConsumer consumer = new QueueingConsumer(channel);
//当连接断开时,队列会自动被删除
channel.basicConsume(queueName,true,consumer);
System.out.println("ReceiveLog2 Waitting for message");
while (true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("ReceiveLog2 receives message " + message);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

  先启动Consumer1,Consumer2,再启动LogProducer。结果如下:

  LogProducer:

  

  Consumer1:

  

  Consumer2:

  

  从输出结果中我们可以看出,扇形交换机所接受到的消息会被分发到所有绑定到该交换机上的队列中,和路由键无关。

二、主题交换机

  1.生产者

  

/**
* 生产者
*/
public class Producer {
private static final String EXCHANGE_NAME = "topic_logs";
// 路由关键字
private static final String[] routingKeys = new String[]{
"quick.orange.rabbit",
"lazy.orange.elephant",
"quick.orange.fox",
"lazy.brown.fox",
"quick.brown.fox",
"quick.orange.male.rabbit",
"lazy.orange.male.rabbit"}; public static void main(String[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(EXCHANGE_NAME, "topic"); //循环发送具有不同routing key的message
for (String routingKey : routingKeys) {
String message = routingKey + "--->biu~";
channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
System.out.println("Producer -> routingkey: " + routingKey + ", send message " + message);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
channel.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
} }
}
}

2.消费者

  Consumer1

  

/**
* 消费者1
*/
public class Consumer1 {
private static final String EXCHANGE_NAME = "topic_logs";
// 路由关键字
private static final String[] routingKeys = new String[]{"*.orange.*"}; public static void main(String[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
channel = connection.createChannel();
//声明队列
String queueName = channel.queueDeclare().getQueue();
//声明交换机
channel.exchangeDeclare(EXCHANGE_NAME, "topic"); //将队列与交换器用routingkey绑定起来
for (String routingKey : routingKeys) {
channel.queueBind(queueName, EXCHANGE_NAME, routingKey);
System.out.println("Consumer1 -> queue: " + queueName + ", exchange_name: " + EXCHANGE_NAME + ", routingKey: " + routingKey);
} //接收消息
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer);
System.out.println("Consumer1 waitting for message"); while (true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody(), "UTF-8");
Envelope envelope = delivery.getEnvelope();
String routingKey = envelope.getRoutingKey();
System.out.println("Consumer1 receive message " + message + ", routingKey: " + routingKey);
} } catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

  Consumer2

  

/**
* 消费者2
*/
public class Consumer2 {
private static final String EXCHANGE_NAME = "topic_logs";
// 路由关键字
private static final String[] routingKeys = new String[]{"*.*.rabbit", "lazy.#"}; public static void main(String[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory();
Connection connection = null;
Channel channel = null;
try {
connection = connectionFactory.newConnection();
channel = connection.createChannel();
//声明队列
String queueName = channel.queueDeclare().getQueue();
//声明交换机
channel.exchangeDeclare(EXCHANGE_NAME, "topic"); //将队列与交换器用routingkey绑定起来
for (String routingKey : routingKeys) {
channel.queueBind(queueName, EXCHANGE_NAME, routingKey);
System.out.println("Consumer2 -> queue: " + queueName + ", exchange_name: " + EXCHANGE_NAME + ", routingKey: " + routingKey);
} //接收消息
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer);
System.out.println("Consumer2 waitting for message"); while (true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody(), "UTF-8");
Envelope envelope = delivery.getEnvelope();
String routingKey = envelope.getRoutingKey();
System.out.println("Consumer2 receive message " + message + ", routingKey: " + routingKey);
} } catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

  同样先运行消费者,再运行生产者,结果如下:

  Producer:

  

  Consumer1:

  

  Consumer2:

  

  由运行结果我们可以看到:消息被交换机按照模式路由键的规则路由到相应的队列中。

代码gitbu地址:https://github.com/wutianqi/rabbitmq-learn.git

参考资料:https://www.cnblogs.com/LipeiNet/p/5978276.html

  

rabbitmq学习(三):rabbitmq之扇形交换机、主题交换机的更多相关文章

  1. rabbitMQ第三篇:采用不同的交换机规则

    在上一篇我们都是采用发送信息到队列然后队列把信息在发送到消费者,其实实际情况并非如此,rabbitMQ其实真正的思想是生产者不发送任何信息到队列,甚至不知道信息将发送到哪个队列.相反生产者只能发送信息 ...

  2. RabbitMq学习笔记——RabbitMQ C的使用

    1.需要用到的参数: 主机名:hostname.端口号:port.交换器:exchange.路由key:routingkey .绑定路由:bindingkey.用户名:user.密码:psw,默认用户 ...

  3. rabbitmq系列五 之主题交换机

    1.主题 在前面的例子中,我们对日志系统进行了改进.使用了direct交换机代替了fanout交换机,从只能盲目的广播消息改进为有可能选择性的接收日志. 尽管直接交换机能够改善我们的日志系统,但是它也 ...

  4. Rabbitmq消息队列(六) 主题交换机

    1.简介 前面学习了有选择性的接收消息,但是却没有办法基于多个标准来接收消息.为了实现这个目的,接下来我们学习如何使用另一种更复杂的交换机 —— 主题交换机. 2.主题交换机 发送到主题交换机(top ...

  5. 【c#】RabbitMQ学习文档(三)Publish/Subscribe(发布/订阅)

    (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个任务会被交付给一个[工人].在这一部分我们将做一些完全不同的事情--我们将向多个 ...

  6. rabbitmq学习(二):rabbitmq(消息队列)的作用以及rabbitmq之直连交换机

    前言 上篇介绍了AMQP的基本概念,组成及其与rabbitmq的关系.了解了这些东西后,下面我们开始学习rabbitmq(消息队列)的作用以及用java代码和rabbitmq通讯进行消息发布和接收.因 ...

  7. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  8. 学习RabbitMQ(三)

    1 用户注册后(会立即提示注册成功),过一会发送短信和邮件通知 发布/订阅模型 以上模式一般是用户注册成功后,写入一条数据到mysql,在发送一条消息到MQ! 如果不用消息中间件(或者简单的做成异步发 ...

  9. RabbitMQ学习系列(三): C# 如何使用 RabbitMQ

    上一篇已经讲了Rabbitmq如何在Windows平台安装,还不了解如何安装的朋友,请看我前面几篇文章:RabbitMQ学习系列一:windows下安装RabbitMQ服务 , 今天就来聊聊 C# 实 ...

随机推荐

  1. 2.3 The Object Model -- Computed Properties

    一.What are computed properties? 1. 简而言之,计算属性让你声明函数为属性.你通过定义一个计算属性作为一个函数来创建一个,当你请求这个属性时,Ember会自动调用这个f ...

  2. Smarty 模板布局继承

    Smarty 模板继承 在覆盖父模板的{block}块以外的地方, 子模板不能定义任何内容.任何在{block}以外的 内容都会被自动忽略. 在子模板和父模板中的{block}内容,可以通过 appe ...

  3. android中代码操作外部SD卡出错:W/System.err(1595): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)

    AndroidManifest.xml 中加上: <uses-permission android:name="android.permission.WRITE_EXTERNAL_ST ...

  4. Mkdocs 搭建

    1. 利用pip安装mkdocs sudo pip install mkdocs 2.如果报pip不存在 或是 报权限错误,要不是pip没有安装,就是python里某个库没有关联上,这时候需要重新安装 ...

  5. SNMP学习笔记之SNMPWALK 命令

    SNMPWALK是一个通过SNMP GET-NEXT类型PDU,实现对目标AGENT的某指定MIB分支信息进行完整提取输出的命令工作. 命令行: snmpwalk [选项] agent [oid] 选 ...

  6. Web漏洞挖掘之网络信息探测

    我们在搜集目标系统信息的时候主要需要搜集的是:目标服务器系统信息(IP,服务器所用系统等):目标网站子域名:目标网站(服务器)的开放端口:目标域名信息.目标网站内容管理系统(CMS)等. 一.子域名搜 ...

  7. linux下如何使用split

    答: 切割文件hello,以每个文件最大10MiB来切割,切割好的文件名前缀为hello.,后缀为二位的数字,切割之后的名字为hello.01,hello.02等等    split -b 10M - ...

  8. BootStrap iCheck插件全选与获取value值的解决方法

    这篇文章主要介绍了BootStrap iCheck插件全选与获取value值的解决方法,解决方法其实很简单,下面小编给大家分享下这方面的知识 在使用jQuery iCheck 插件的时候遇到了一个问题 ...

  9. Hadoop平台的基本组成与生态系统

    Hadoop系统运行于一个由普通商用服务器组成的计算集群上,该服务器集群在提供大规模分布式数据存储资源的同时,也提供大规模的并行化计算资源. 在大数据处理软件系统上,随着Apache Hadoop系统 ...

  10. Python yield 用法

    一.环境 python 3.6 二.yield 说明 yield 是一个生成器,可以用于迭代.也是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值. 重点是: ...