前言

上篇我们学习了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. CCPC-Wannafly Winter Camp Day1 (Div2, onsite)

    Replay Dup4: 要是不挂机,再多仔细想想就好了 J确实自闭好久,一直在想正确性,最后数据错了,喵喵喵? 还是要保证充足的休息啊,中间睡了一小会儿,也不知道睡了多久,醒来他们就又过了一道 要发 ...

  2. ng-深度学习-课程笔记-12: 深度卷积网络的实例探究(Week2)

    1 实例探究( Cast Study ) 这一周,ng对几个关于计算机视觉的经典网络进行实例分析,LeNet-5,AlexNet,VGG,ResNet,Inception. 2 经典网络( Class ...

  3. Python ConfigParser的使用

    1.基本的读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该sect ...

  4. Java开发之JDK配置

    windows下配置JDK环境变量:       1.安装JDK,安装过程中可以自定义安装目录等信息,例如我们选择安装目录为D:/java/jdk1.5.0_08:    2.安装完成后,右击“我的电 ...

  5. Linux内核分析06

    进程的描述和进程的创建 一,进程的描述 进程控制块PCB——task_struct (进程描述符),为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. struc ...

  6. postgresql常用操作

    需要安装的软件包: apt-get install postgresql postgresql-client-9.1 postgresql-common postgresql-9.1 postgres ...

  7. HDU 3709 Balanced Number(数位DP)题解

    思路: 之前想直接开左右两边的数结果爆内存... 枚举每次pivot的位置,然后数位DP,如果sum<0返回0,因为已经小于零说明已经到了pivot右边,继续dfs只会越来越小,且dp数组会炸 ...

  8. SharePoint研究之表单登录配置

    本文将演示SharePoint怎样配置表单(Form)登录,后续文章将研究 无密码登录.编程添加用户组.编程添加用户.编程添加文件夹.编程分享文件夹(权限分配)等. 知识点:SharePoint.Sq ...

  9. 《A Tour of PostgreSQL Internals》学习笔记——查询处理分析

           终于要迎来postgresql的<A Tour of PostgreSQL Internals>系列的最后一篇了.学习是不能拖延的事儿,越拖延事情越多.不废话,一起来看看吧~ ...

  10. python之urllib2简单解析HTML页面之篇一

    一.urllib2简单获取html页面 #!/usr/bin/env python # -*- coding:utf-8 -*- import urllib2 response = urllib2.u ...