有选择的接收消息。

上一节我们使用的是fanout exchange来实现消息的发布/订阅模式,这并没有给我们带来多大的灵活性——它只能够让人盲目地进行广播。而本节我们采用direct类型的交换器来实现有选择的接收消息。直接交换器背后的路由算法很简单——消息传递到绑定键与消息的路由键完全匹配的队列。

如上这个设置中,我们可以看到与它绑定的两个队列的直接交换X。第一个队列用绑定键橙色绑定,第二个队列有两个绑定,一个绑定键为黑色,另一个绑定键为绿色。

在这个设置里面,一个被发布到交换器里的带有橙色路由键的消息将被路由到队列Q1中,带有黑色或绿色路由键的消息将去往队列Q2中,所有其他消息将被舍弃掉。

下面这个是多重绑定,该绑定相似与上一节的发布/订阅模式

使用相同的绑定键绑定多个队列是完全合法的。在我们的示例中,我们可以在X和Q1之间添加绑定键黑。在这种情况下,直接交换将表现为fanout类型,并将消息广播给所有匹配的队列。带有black路由键的消息将被发送到Q1和Q2。

接下来,我们将采用这个模型,代替fanout来发送消息,以这种方式进行,接收程序放可以选择性的接收消息。

该篇与上篇区别仅在于,发布和订阅方的交换器的类型变为direct,同时设置发布消息的路由键,本篇将其设置为“error”,将订阅方其中一个队列的路由键设置为“error”,另一个设置为“bug”,则运行后,只有路由键和队列名称相同的一方能够收到消息,另一个bug路由键的收不到消息。

代码如下(在上篇代码上改造,修改的代码加上了下划线以便区分):

发布方:

package com.rabbitmq.HelloWorld;

import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; public class Publish { private static final String EXCHANGE_NAME = "exchangeB"; public static void main(String[] args) throws IOException, TimeoutException {
// TODO Auto-generated method stub
// 创建工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.10.185");
factory.setUsername("admin");
factory.setPassword("123456");
factory.setPort(5672);
// 创建连接
Connection connetion = factory.newConnection();
// 获得信道
Channel channel = connetion.createChannel();
// 声明交换器(声明了一个名字位exchangeA,类型修改fanout为direct类型的交换器)
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
String message = "555,2,2,33,66";
// 发送消息,将第二项参数routingkey修改为error
channel.basicPublish(EXCHANGE_NAME, "error", null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
channel.close();
connetion.close();
} }

订阅方一,路由键为“error”

package com.rabbitmq.HelloWorld;

import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Subscribe { private static final String EXCHANGE_NAME = "exchangeB";
private static final String QUEUE_NAME = "queueA"; public static void main(String[] args) throws IOException, TimeoutException {
// TODO Auto-generated method stub
// 创建工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.10.185");
factory.setUsername("admin");
factory.setPassword("123456");
factory.setPort(5672);
// 创建连接
Connection connetion = factory.newConnection();
// 获得信道
Channel channel = connetion.createChannel();
// 声明交换器(声明了一个名字位exchangeA,类型修改fanout为direct的交换器)
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
// 声明一个队列,在此采用临时队列
String queueName = channel.queueDeclare().getQueue();
// channel.queueDeclare(QUEUE_NAME, true, false, false, null);
// 队列和交换器进行绑定,并设定路由键为error
channel.queueBind(queueName, EXCHANGE_NAME, "error");
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
// TODO Auto-generated method stub
String message = new String(body,"utf-8");
System.out.println("[x] received'"+message+"'");
}
};
channel.basicConsume(queueName, consumer);
} }

订阅方二(路由键为“bug”)

import java.io.IOException;
import java.util.concurrent.TimeoutException; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties; public class Subscribe { private static final String EXCHANGE_NAME = "exchangeB";
private static final String QUEUE_NAME = "queueA"; public static void main(String[] args) throws IOException, TimeoutException {
// TODO Auto-generated method stub
// 创建工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.10.185");
factory.setUsername("admin");
factory.setPassword("123456");
factory.setPort(5672);
// 创建连接
Connection connetion = factory.newConnection();
// 获得信道
Channel channel = connetion.createChannel();
// 声明交换器(声明了一个名字位exchangeA,修改fanout类型为direct类型的交换器�?
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
// 声明�?个队列,在此采用临时队列
String queueName = channel.queueDeclare().getQueue();
// channel.queueDeclare(QUEUE_NAME, true, false, false, null);
// 队列和交换器进行绑定,未设定路由键
channel.queueBind(queueName, EXCHANGE_NAME, "bug");
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
BasicProperties properties, byte[] body) throws IOException {
// TODO Auto-generated method stub
String message = new String(body,"utf-8");
System.out.println("[x] received'"+message+"'");
}
};
channel.basicConsume(queueName, consumer);
} }

运行结果:

下面这个是在另一个项目中,没有引进日志打印的包,红色忽略即可

效果已经呈现了。

有选择的接收消息。

上一节我们使用的是fanout exchange来实现消息的发布/订阅模式,这并没有给我们带来多大的灵活性——它只能够让人盲目地进行广播。而本节我们采用direct类型的交换器来实现有选择的接收消息。直接交换器背后的路由算法很简单——消息传递到绑定键与消息的路由键完全匹配的队列。

如上这个设置中,我们可以看到与它绑定的两个队列的直接交换X。第一个队列用绑定键橙色绑定,第二个队列有两个绑定,一个绑定键为黑色,另一个绑定键为绿色。

在这个设置里面,一个被发布到交换器里的带有橙色路由键的消息将被路由到队列Q1中,带有黑色或绿色路由键的消息将去往队列Q2中,所有其他消息将被舍弃掉。

下面这个是多重绑定,该绑定相似与上一节的发布/订阅模式

使用相同的绑定键绑定多个队列是完全合法的。在我们的示例中,我们可以在X和Q1之间添加绑定键黑。在这种情况下,直接交换将表现为fanout类型,并将消息广播给所有匹配的队列。带有black路由键的消息将被发送到Q1和Q2。

接下来,我们将采用这个模型,代替fanout来发送消息,以这种方式进行,接收程序放可以选择性的接收消息。

该篇与上篇区别仅在于,发布和订阅方的交换器的类型变为direct,同时设置发布消息的路由键,本篇将其设置为“error”,将订阅方其中一个队列的路由键设置为“error”,另一个设置为“bug”,则运行后,只有路由键和队列名称相同的一方能够收到消息,另一个bug路由键的收不到消息。

代码如下(在上篇代码上改造,修改的代码加上了下划线以便区分):

发布方:

[java] view plain copy

 
  1. package com.rabbitmq.HelloWorld;
  2. import java.io.IOException;
  3. import java.util.concurrent.TimeoutException;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. import com.rabbitmq.client.ConnectionFactory;
  7. public class Publish {
  8. <u>private static final String EXCHANGE_NAME = "exchangeB";</u>
  9. public static void main(String[] args) throws IOException, TimeoutException {
  10. // TODO Auto-generated method stub
  11. //      创建工厂
  12. ConnectionFactory factory = new ConnectionFactory();
  13. factory.setHost("192.168.10.185");
  14. factory.setUsername("admin");
  15. factory.setPassword("123456");
  16. factory.setPort(5672);
  17. //      创建连接
  18. Connection connetion = factory.newConnection();
  19. //      获得信道
  20. Channel channel = connetion.createChannel();
  21. //      <u>声明交换器(声明了一个名字位exchangeA,类型修改fanout为direct类型的交换器)
  22. channel.exchangeDeclare(EXCHANGE_NAME, "direct");</u>
  23. String message = "555,2,2,33,66";
  24. //      <u>发送消息,将第二项参数routingkey修改为error
  25. channel.basicPublish(EXCHANGE_NAME, "error", null, message.getBytes());</u>
  26. System.out.println(" [x] Sent '" + message + "'");
  27. channel.close();
  28. connetion.close();
  29. }
  30. }

订阅方一,路由键为“error”

[java] view plain copy

 
  1. package com.rabbitmq.HelloWorld;
  2. import java.io.IOException;
  3. import java.util.concurrent.TimeoutException;
  4. import com.rabbitmq.client.Channel;
  5. import com.rabbitmq.client.Connection;
  6. import com.rabbitmq.client.ConnectionFactory;
  7. import com.rabbitmq.client.Consumer;
  8. import com.rabbitmq.client.DefaultConsumer;
  9. import com.rabbitmq.client.Envelope;
  10. import com.rabbitmq.client.AMQP.BasicProperties;
  11. public class Subscribe {
  12. <u>private static final String EXCHANGE_NAME = "exchangeB";</u>
  13. private static final String QUEUE_NAME = "queueA";
  14. public static void main(String[] args) throws IOException, TimeoutException {
  15. // TODO Auto-generated method stub
  16. //      创建工厂
  17. ConnectionFactory factory = new ConnectionFactory();
  18. factory.setHost("192.168.10.185");
  19. factory.setUsername("admin");
  20. factory.setPassword("123456");
  21. factory.setPort(5672);
  22. //      创建连接
  23. Connection connetion = factory.newConnection();
  24. //      获得信道
  25. Channel channel = connetion.createChannel();
  26. //      <u>声明交换器(声明了一个名字位exchangeA,类型修改fanout为direct的交换器)
  27. channel.exchangeDeclare(EXCHANGE_NAME, "direct");</u>
  28. //      声明一个队列,在此采用临时队列
  29. String queueName = channel.queueDeclare().getQueue();
  30. //      channel.queueDeclare(QUEUE_NAME, true, false, false, null);
  31. //      队列和交换器进行绑定,并设定路由键为error
  32. <u>channel.queueBind(queueName, EXCHANGE_NAME, "error");</u>
  33. System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
  34. Consumer consumer = new DefaultConsumer(channel){
  35. @Override
  36. public void handleDelivery(String consumerTag, Envelope envelope,
  37. BasicProperties properties, byte[] body) throws IOException {
  38. // TODO Auto-generated method stub
  39. String message = new String(body,"utf-8");
  40. System.out.println("[x] received'"+message+"'");
  41. }
  42. };
  43. channel.basicConsume(queueName, consumer);
  44. }
  45. }

订阅方二(路由键为“bug”)

[java] view plain copy

 
  1. import java.io.IOException;
  2. import java.util.concurrent.TimeoutException;
  3. import com.rabbitmq.client.Channel;
  4. import com.rabbitmq.client.Connection;
  5. import com.rabbitmq.client.ConnectionFactory;
  6. import com.rabbitmq.client.Consumer;
  7. import com.rabbitmq.client.DefaultConsumer;
  8. import com.rabbitmq.client.Envelope;
  9. import com.rabbitmq.client.AMQP.BasicProperties;
  10. public class Subscribe {
  11. <u>private static final String EXCHANGE_NAME = "exchangeB";</u>
  12. private static final String QUEUE_NAME = "queueA";
  13. public static void main(String[] args) throws IOException, TimeoutException {
  14. // TODO Auto-generated method stub
  15. //      创建工厂
  16. ConnectionFactory factory = new ConnectionFactory();
  17. factory.setHost("192.168.10.185");
  18. factory.setUsername("admin");
  19. factory.setPassword("123456");
  20. factory.setPort(5672);
  21. //      创建连接
  22. Connection connetion = factory.newConnection();
  23. //      获得信道
  24. Channel channel = connetion.createChannel();
  25. //      <u>声明交换器(声明了一个名字位exchangeA,修改fanout类型为direct类型的交换器�?
  26. channel.exchangeDeclare(EXCHANGE_NAME, "direct");</u>
  27. //      声明�?个队列,在此采用临时队列
  28. String queueName = channel.queueDeclare().getQueue();
  29. //      channel.queueDeclare(QUEUE_NAME, true, false, false, null);
  30. //      <u>队列和交换器进行绑定,未设定路由键
  31. channel.queueBind(queueName, EXCHANGE_NAME, "bug");</u>
  32. System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
  33. Consumer consumer = new DefaultConsumer(channel){
  34. @Override
  35. public void handleDelivery(String consumerTag, Envelope envelope,
  36. BasicProperties properties, byte[] body) throws IOException {
  37. // TODO Auto-generated method stub
  38. String message = new String(body,"utf-8");
  39. System.out.println("[x] received'"+message+"'");
  40. }
  41. };
  42. channel.basicConsume(queueName, consumer);
  43. }
  44. }

运行结果:

下面这个是在另一个项目中,没有引进日志打印的包,红色忽略即可

效果已经呈现了。

官网英文版学习——RabbitMQ学习笔记(六)Routing的更多相关文章

  1. 官网英文版学习——RabbitMQ学习笔记(一)认识RabbitMQ

    鉴于目前中文的RabbitMQ教程很缺,本博主虽然买了一本rabbitMQ的书,遗憾的是该书的代码用的不是java语言,看起来也有些不爽,且网友们不同人学习所写不同,本博主看的有些地方不太理想,为此本 ...

  2. 官网英文版学习——RabbitMQ学习笔记(十)RabbitMQ集群

    在第二节我们进行了RabbitMQ的安装,现在我们就RabbitMQ进行集群的搭建进行学习,参考官网地址是:http://www.rabbitmq.com/clustering.html 首先我们来看 ...

  3. Unity shader 官网文档全方位学习(一)

    转载:https://my.oschina.net/u/138823/blog/181131 摘要: 这篇文章主要介绍Surface Shaders基础及Examples详尽解析 What?? Sha ...

  4. 利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)

    利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)   作者:王可利(Star·星星) 总结: 今天学习的jQ类库的使用,代码重复的比较多需要完善.严格区分大小写,在 $(" ...

  5. 官网英文版学习——RabbitMQ学习笔记(二)RabbitMQ安装

    一.安装RabbitMQ的依赖Erlang 要进行RabbitMQ学习,首先需要进行RabbitMQ服务的安装,安装我们可以根据官网指导进行http://www.rabbitmq.com/downlo ...

  6. 官网英文版学习——RabbitMQ学习笔记(三)Hello World!

    参考http://www.rabbitmq.com/tutorials/tutorial-one-java.html,我们直接上代码,由于我们的RabbitMQ服务是安装在虚拟机上的,具体参考上一节. ...

  7. 官网英文版学习——RabbitMQ学习笔记(八)Remote procedure call (RPC)

    在第四篇学习笔记中,我们学习了如何使用工作队列在多个工作者之间分配耗时的任务.   但是,如果我们需要在远程计算机上运行一个函数并等待结果呢?这是另一回事.这种模式通常称为远程过程调用或RPC.   ...

  8. 官网英文版学习——RabbitMQ学习笔记(七)Topic

    在上一篇中使用直接交换器改进了我们的系统,使得它能够有选择的进行接收消息,但它仍然有局限性——它不能基于多个条件进行路由.本节我们就进行能够基于多个条件进行路由的topics exchange学习. ...

  9. 官网英文版学习——RabbitMQ学习笔记(五)Publish/Subscribe

    发布/订阅模式:把一个消息发送给多个消费者. 前几篇文章的思想是,我们好像看到了生产者将消息直接发送给queue,然后消费者也从queue中进行消费.其实并非如此,RabbitMQ中的消息传递模型的核 ...

随机推荐

  1. Linux centos7 VMware Apache访问日志不记录静态文件、访问日志切割、静态元素过期时间

    一.Apache访问日志不记录静态文件 网站大多元素为静态文件,如图片.css.js等,这些元素可以不用记录 vim /usr/local/apache2.4/conf/extra/httpd-vho ...

  2. Linux centos7 Linux网络相关、firewalld和netfilter、netfilter5表5链介绍、iptables语法

    一. Linux网络相关 yum install net-tools ifconfig查看网卡ip ifup ens33开启网卡 ifdown ens33关闭网卡 设定虚拟网卡ens33:0 mii- ...

  3. SSIS 無法將保護的 XML 節點 "DTS:Password" 解密,錯誤為 0x8009000B "機碼用在特定狀態時無效

    发现之前部署的SSIS,执行失败,查看日志 來源: 描述: 無法將保護的 XML 節點 -- ::-- ::-- :: DataReader 來源 [] 描述: System.Exception: S ...

  4. Github 第三方授权登录教程

    Github 第三方授权登录教程 ####大致流程图 ####1.首先注册一个github帐号,Applications>Developer applications>Register a ...

  5. 在Windows中实现Java调用DLL(转载)

    本文提供调用本地 C 代码的 Java 代码示例,包括传递和返回某些常用的数据类型.本地方法包含在特定于平台的可执行文件中.就本文中的示例而言,本地方法包含在 Windows 32 位动态链接库 (D ...

  6. [转]ubuntu备份与恢复

    在 使用Ubuntu之前,相信很多人都有过使用Windows系统的经历.如果你备份过Windows系统,那么你一定记忆犹新:首先需要找到一个备份工 具(通常都是私有软件),然后重启电脑进入备份工具提供 ...

  7. 十 Restful风格

    1 restful风格化,url上的参数通过{}点符绑定,RequestMapping("item/{id}") 2 点位符参数名与方法参数名不一致时,通过@PathVariabl ...

  8. 一、linux基础-对文件操作

    1.1文件夹创建-复制-移动-重命名-删除1.创建文件夹mkdir zjbdir 2.复制文件/文件夹复制文件到:当前目录cp -r zjbdir  zjbdir201600819复制文件到:当前目录 ...

  9. 通过CrawlSpider对招聘网站进行整站爬取(拉勾网实战)

    爬虫首先要明确自己要爬取的网站以及内容 进入拉勾网的网站然后看看想要爬取什么内容职位,薪资,城市,经验要求学历要求,全职或者兼职职位诱惑,职位描述提取公司的名称 以及 在拉勾网的url等等 然后在na ...

  10. JDBC和连接池

    JDBC 所有的数据库操作框架都是用在JDBC的基础上做多次封装的,因为JDBC的操作很复杂 引入Jar包 连接数据库操作 书写sql语句,传参 查询,取值 关闭连接 //1.注册驱动(静态方法)(包 ...