前两篇文章,是建立一个简单的日志系统,可以广播消息给多个消费者.这篇文章,讲一下路由.只订阅部分消息.举个例子: 日志其中一个队列, 只接受关于某一类的信息

Bindings(绑定)

绑定表示的是交换器和队列的关系.

绑定可以设定额外的routingKey参数,

而绑定键: severity

绑定前面的代码用过的:

channel.queueBind(queueName, EXCHANGE_NAME, severity);

绑定键关键取决于转换器的类型,如果是fanout类型,可忽略此参数

Direct exchange

前面讲的日志系统,是广播消息给所有的消费者,但是如果我们需要一个程序仅仅是将日志消息写入磁盘接收严重错误,对于其他的信息,不接收. 前面我们用的fanout转发器,不够灵活,而如果使用direct转发器的话,消息被推送至绑定键(binding key)和消息发布的选择键(routing key)完全匹配的队列

图如下:

RabbitMQ-路由_官网

在上图中, 发布到交换机上消息路由键是orange的,都被传到队列Q1,路由键为黑色或者绿色的,都被传到Q2上.其他的消息就被丢弃了–Direct exchange+routingKey,过滤感兴趣消息. 一个队列可以绑定多个routingKey

看看代码吧(依旧是先运行消费者,再运行生产者)

消费者代码

package com.tgb.kwy.Routing;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.Random;

/**
* Description
*
* @author kongwy 15732621629@163.com
* @version 1.0
* @date 2018-07-09-17 -13
*/
public class ReceiveLogsDirect {
private static final String EXCHANGE_NAME = "direct_logs";
private static final String[] SEVERITIES = {"info", "warning", "error"};

public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.159.132");/*设置rabbitmq所在主机ip或主机名*/
/*指定用户名和密码*/
factory.setUsername("admin");
factory.setPassword("admin");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
String queueName = channel.queueDeclare().getQueue();

if (SEVERITIES.length < 1) {
System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]");
System.exit(1);
}

String severity=getSeverity();
channel.queueBind(queueName, EXCHANGE_NAME, severity);

System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
}
};
channel.basicConsume(queueName, true, consumer);
}
private static String getSeverity(){
Random random=new Random();
int ranVal=random.nextInt(3);
return SEVERITIES[ranVal];
}
}

运行结果

RabbitMQ-路由_java_02

生产者代码

package com.tgb.kwy.Routing;

import com.rabbitmq.client.*;

import java.util.Random;
import java.util.UUID;

/**
* Description
*
* @author kongwy 15732621629@163.com
* @version 1.0
* @date 2018-07-09-17 -07
*/
public class EmitLogDirect {
private static final String EXCHANGE_NAME="direct_logs";
//日志分类
private static final String[] SEVERITIES = { "info", "warning", "error" };
public static void main(String[] args) throws java.io.IOException{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.159.132");/*设置rabbitmq所在主机ip或主机名*/
/*指定用户名和密码*/
factory.setUsername("admin");
factory.setPassword("admin");
try{
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
for (int i = 0; i <5 ; i++) {
String severity = getSeverity();
String message=severity+"_log"+UUID.randomUUID().toString();

channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + severity + "':'" + message + "'");

}

channel.close();
connection.close();
}catch (Exception e){

}

}

private static String getSeverity(){
Random random=new Random();
int ranVal=random.nextInt(3);
return SEVERITIES[ranVal];
}
}

发布了几个随机的消息

运行结果如下:

RabbitMQ-路由_官网_03

代码逻辑部分: 生产者是随机产生消息, 消费者的队列接收内容,也是直接设定的随机的.然后如果是warning,就接收了生产者生产的消息了.

注:代码来自官网.官网对于概念性的内容,讲解的还是很清楚的