topic的路由规则里使用【.】号分隔单词,使用【*】号匹配1个单词,使用【#】匹配多个.和多个*。

在下面的例子中:

logger.*可以匹配logger.error和logger.warning,但logger*.error只能匹配logger.error

logger#可以匹配到logger.error和logger.warning。

下面的例子使用topic接收警告、错误的日志,并根据匹配的路由规则发送给不同的Queue队列来处理的例子:

日志生产者SenderWithTopicExchange

 package com.yzl.test2;

 import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; /**
* 使用topic交换器发送消息
* 分为警告和错误2种日志
* @author: yzl
* @date: 2016-10-22
*/
public class SenderWithTopicExchange {
//交换器名称
private static final String EXCHANGE_NAME = "myTopicExchange";
//路由键的前缀
private static final String BASE_ROUTING_KEY = "logger."; public static void main(String[] args) throws Exception {
//使用CountDownLatch控制2个线程一起运行
final CountDownLatch cdl = new CountDownLatch(2);
//连接到rabbitmq服务器
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
//创建一个信道
final Channel channel = connection.createChannel();
//定义一个名字为topicExchange的topic类型的exchange
channel.exchangeDeclare(EXCHANGE_NAME, "topic"); ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(new Runnable() {
@Override
public void run() {
try {
cdl.await();
//发送警告日志,绑定路由键:logger.warning
String warningMsg = "warning message is :";
for(int i=1; i<800; i++){
System.out.println("发送警告消息:" + warningMsg+i);
channel.basicPublish(EXCHANGE_NAME, BASE_ROUTING_KEY + "warning", null, (warningMsg+i).getBytes());
Thread.sleep(2000L);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
pool.submit(new Runnable() {
@Override
public void run() {
try {
cdl.await();
//发送错误日志,绑定路由键:logger.error
String errorMsg = "error message is :";
for(int i=1; i<1000; i++){
System.out.println("发送错误消息:" + errorMsg+i);
channel.basicPublish(EXCHANGE_NAME, BASE_ROUTING_KEY + "error", null, (errorMsg+i).getBytes());
Thread.sleep(2000L);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}); cdl.countDown();
cdl.countDown();
}
}

消息消费者ReceiverWithTopicExchange

 package com.yzl.test2;

 import java.io.IOException;

 import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope; /**
* 使用topic交换器接收消息
*
* @author: yzl
* @date: 2016-10-22
*/
public class ReceiverWithTopicExchange {
// 交换器名称
private static final String EXCHANGE_NAME = "myTopicExchange"; public static void main(String[] args) throws Exception {
// 连接到rabbitmq服务器
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
// 创建一个信道
final Channel channel = connection.createChannel();
// 定义一个名字为topicExchange的topic类型的exchange
channel.exchangeDeclare(EXCHANGE_NAME, "topic"); //定义接收警告消息的队列
channel.queueDeclare("warningQueue", false, false, false, null);
//定义接收错误消息的队列
channel.queueDeclare("errorQueue", false, false, false, null);
//定义接收所有级别日志消息的队列
channel.queueDeclare("allLoggerQueue", false, false, false, null); //使用logger.warning路由键绑定myTopicExchange与warningQueue
channel.queueBind("warningQueue", EXCHANGE_NAME, "logger.warning");
//使用logger.error路由键绑定myTopicExchange与errorQueue
channel.queueBind("errorQueue", EXCHANGE_NAME, "logger.error");
//使用logger.*路由规则绑定myTopicExchange与allLoggerQueue
channel.queueBind("allLoggerQueue", EXCHANGE_NAME, "logger.*"); //只处理警告日志,使用手动ack确认
channel.basicConsume("warningQueue", false, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body);
System.out.println("warningQueue accept a warning msg :" + msg);
channel.basicAck(envelope.getDeliveryTag(), false);
}
});
//只处理错误日志,使用手动ack确认
channel.basicConsume("errorQueue", false, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body);
System.out.println("errorQueue accept a error msg :" + msg);
channel.basicAck(envelope.getDeliveryTag(), false);
}
});
//处理警告和错误日志,使用手动ack确认
channel.basicConsume("allLoggerQueue", false, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body);
System.out.println("allLoggerQueue accept a logger msg :" + msg);
channel.basicAck(envelope.getDeliveryTag(), false);
}
});
}
}

结果输出:

发送警告消息:warning message is :1
发送错误消息:error message is :1
发送警告消息:warning message is :2
发送错误消息:error message is :2
发送错误消息:error message is :3
发送警告消息:warning message is :3
allLoggerQueue accept a logger msg :error message is :1
allLoggerQueue accept a logger msg :warning message is :1
errorQueue accept a error msg :error message is :1
warningQueue accept a warning msg :warning message is :1
warningQueue accept a warning msg :warning message is :2
errorQueue accept a error msg :error message is :2
allLoggerQueue accept a logger msg :warning message is :2
allLoggerQueue accept a logger msg :error message is :2
allLoggerQueue accept a logger msg :warning message is :3
errorQueue accept a error msg :error message is :3
warningQueue accept a warning msg :warning message is :3
allLoggerQueue accept a logger msg :error message is :3

消息处理流程:

RabbitMQ学习笔记3-使用topic交换器的更多相关文章

  1. RabbitMQ学习笔记4-使用fanout交换器

    fanout交换器会把发送给它的所有消息发送给绑定在它上面的队列,起到广播一样的效果. 本里使用实际业务中常见的例子, 订单系统:创建订单,然后发送一个事件消息 积分系统:发送订单的积分奖励 短信平台 ...

  2. RabbitMQ学习笔记(五) Topic

    更多的问题 Direct Exchange帮助我们解决了分类发布与订阅消息的问题,但是Direct Exchange的问题是,它所使用的routingKey是一个简单字符串,这决定了它只能按照一个条件 ...

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

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

  4. RabbitMQ学习笔记1-hello world

    安装过程略过,一搜一大把. rabbitmq管理控制台:http://localhost:15672/   默认账户:guest/guest RabbitMQ默认监听端口:5672 JAVA API地 ...

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

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

  6. (转) Rabbitmq学习笔记

    详见原文: http://blog.csdn.net/shatty/article/details/9529463 Rabbitmq学习笔记

  7. RabbitMQ学习笔记五:RabbitMQ之优先级消息队列

    RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...

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

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

  9. RabbitMQ学习笔记(六) RPC

    什么RPC? 这一段是从度娘摘抄的. RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的 ...

随机推荐

  1. ubuntu 命令的快捷启动

    目前我知道的有三种方式 第一种,在配置文件 .bashrc 中 配置alias ,追加到文件末尾就行 如下: alias tmout='tail -f /usr/local/oakcloud/tomc ...

  2. [Leetcode][JAVA] Pascal's Triangle I, II

    Pascal's Triangle: Given numRows, generate the first numRows of Pascal's triangle. For example, give ...

  3. python 多线程 笔记(一)

    #coding=utf-8 import threading from time import sleep, ctime loops = [4,2] def loop(nloop, nsec): pr ...

  4. Spring MVC静态资源处理(在applicationContex.xml文件中进行配置)

    优雅REST风格的资源URL不希望带 .html 或 .do 等后缀.由于早期的Spring MVC不能很好地处理静态资源,所以在web.xml中配置DispatcherServlet的请求映射,往往 ...

  5. 对象池与.net—从一个内存池实现说起

    本来想写篇关于System.Collections.Immutable中提供的ImmutableList里一些实现细节来着,结果一时想不起来源码在哪里--为什么会变成这样呢--第一次有了想写分析的源码 ...

  6. Android编译错误, Ignoring InnerClasses attribute for an anonymous inner class

    今天在做android项目时,加入第三方包,一编译就报错.错误如下:[2012-01-13 14:51:25 - xxx] Dx warning: Ignoring InnerClasses attr ...

  7. 移动App的REST API设计实践

    原文:http://www.jianshu.com/p/23cccb3a90b1 通讯协议 一些只是对服务器数据进行CRUD操作的App,通常采用HTTP协议,为了安全也可以采用HTTPS协议.IM软 ...

  8. Java Config 下的Spring Test方式

    用了三种方式: 1.纯手动取bean: package com.wang.test; import com.marsmother.commission.core.config.MapperConfig ...

  9. 学习WPF——元素绑定

    概念 从源对象提取一些信息,并用这些信息设置目标对象的属性 示例 在给TextBlock控件的FontSize属性赋值时,我们使用了绑定表达式 数据绑定表达式使用XAML的标记扩展(因此具有花括号)( ...

  10. 无线客户端框架设计(5.1):将JSON映射为实体对象(iOS篇)

    iOS开发人员已经习惯于将JSON转换为字典或者数组来进行操作了,接下来我要做的事情,可能匪夷所思,但是,对WP和Android开发人员而言,他们更倾向于将JSON转换为实体对象进行操作. 我所设计的 ...