前言

上篇我们学习了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. xml转为array

    PHP实现微信支付,微信支付宝返回的xml结果如下: <xml>   <appid><![CDATA[wx2421b1c4370ec43b]]></appid ...

  2. 5.5 Components -- Customizing A Compnent's Element

    一.概述 默认的,每一个组件都基于一个<div>元素.如果你在开发者工具中查看一个渲染的组件,你将会看到一个像这样的DOM表示: <div id="ember180&quo ...

  3. python中的shallow copy 与 deep copy

    今天在写代码的时候遇到一个奇葩的问题,问题描述如下: 代码中声明了一个list,将list作为参数传入了function1()中,在function1()中对list进行了del()即删除了一个元素. ...

  4. python中的切片

    python中提供了一种很方便的方法来完成取出指定范围内的元素,这种方法就是切片(Slice). 以下为切片的例子: In [1]: L = ['Michael', 'Sarah', 'Tracy', ...

  5. 人脸识别技术大总结(1):Face Detection & Alignment

    http://blog.jobbole.com/85783/     首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他技术 - 导航条 - 首页 最新文章 IT 职场 前端 - Ja ...

  6. c++第十九天

    p109~p110: C风格字符串 特点: 1.不方便,不安全,尽量不使用. 2.必须以 '\0'结束.(只有这样才能使用C风格字符串函数) 3.一般利用指针操作这些字符. 4.可以用字符串字面值来初 ...

  7. bzoj2456 / P2397 yyy loves Maths VI (mode)

    P2397 yyy loves Maths VI (mode) 神奇的摩尔投票法(大雾) 保证众数个数大于一半. 两两相消,剩下的那个必定是众数. 我们只要开2个变量,一个存个数,一个存值即可. (l ...

  8. mybatis的namespace

    Mybatis的namespace是用来绑定Dao接口的,使用了namespace之后就可以不用写接口实现类,dao接口的方法对应mapper.xml中的sql语句. 详情见:https://blog ...

  9. scss使用指南--每天一点

    我们平时都称之为 Sass,其实可分成sass和scss, 其中Sass 是以严格的缩进式语法规则来书写,不带大括号({})和分号(;),以".sass"后缀为扩展名:而 SCSS ...

  10. 更改idea快捷键方式为eclipse风格

    打开配置窗口 菜单栏中的File-settings 或者快捷键 ctrl+alt+s 设置keymap 在弹出的setting页面中左侧导航中选择Keymap: 在keymaps下拉列表中选择Ecli ...