模式说明
路由模式特点:
队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
消息的发送方在 向Exchange发送消息时,也必须指定消息的 RoutingKey。
Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息
图解:
P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列。
C1:消费者,其所在队列指定了需要routing key 为 error 的消息 C2:消费者,其所在队列指定了需要routing key
为 info、error、warning 的消息。
代码示例
消息生产者
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ProducerRouterMain {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
//设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/itcast");
factory.setUsername("wujian");
factory.setPassword("wujian");
Connection connection=factory.newConnection();
Channel channel =connection.createChannel();
/** public DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal,Map<String, Object> arguments) throws IOException {
return this.exchangeDeclare(exchange, type.getType(), durable, autoDelete, arguments);
String exchange 交换机名称
BuiltinExchangeType type 交换机类型
DIRECT("direct"), 点对点交换机
FANOUT("fanout"), 广播形式的交换机
TOPIC("topic"), 通配符形式的交换机
HEADERS("headers"); 很少用不做学习
boolean durable 是否持久化
boolean autoDelete 是否自动删除
boolean internal 内部 一般设置为false
Map<String, Object> arguments 参数
}*/
//创建交换机
String exchange = "log_direct";
channel.exchangeDeclare(exchange , BuiltinExchangeType.DIRECT,true,false,false,null);
/** public com.rabbitmq.client.AMQP.Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
queue 队列的名称
durable 是否持久化,当mq重启之后还在
exclusive 是否独占,只有一个消费者监听这个队列
当connection 关闭的时候删除这个队列
autoDelete 是否自动删除,没有消费者的时候删除
arguments 参数
}*/
//创建队列
String aliBaba = "alibaba_direct_log";
String microsoft = "microsoft_direct_log";
channel.queueDeclare(aliBaba,true,false,false,null);
channel.queueDeclare(microsoft,true,false,false,null);
/**交换机和队列绑定*/
// 队列1的绑定
channel.queueBind(aliBaba, exchange, "error");
// 队列2的绑定 ,绑定了三个key
channel.queueBind(microsoft, exchange, "error");
channel.queueBind(microsoft, exchange, "info");
channel.queueBind(microsoft, exchange, "warning");
// 发送消息
String messages = "日志:张三使用了查询方法.....log.info";
// exchangeName 交换机,第二个是路由key没有就是""
channel.basicPublish(exchange, "info", null, messages.getBytes());
// 释放资源
channel.close();
connection.close();
}
}
消息消费者1
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerRouter {
public static void main(String[] args) throws IOException, TimeoutException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/itcast");
factory.setUsername("wujian");
factory.setPassword("wujian");
//创建连接
Connection connection =factory.newConnection();
Channel channel =connection.createChannel();
String aliBaba = "alibaba_direct_log";
// 创建 queue消费
DefaultConsumer consumer = new DefaultConsumer(channel) {
// 这个是一个回调方法,当收到消息之后会自动执行该方法
/****
* consumerTag 标识 编号
* envelope 获取一些信息例如交换机 key,路由
* properties 配置信息
* body 数据
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
// System.out.println("标识:" + consumerTag);
// System.out.println("一些信息" + envelope.getExchange());
// System.out.println("这个是路由,其实是队列名称" + envelope.getRoutingKey());
// System.out.println("消息序号" + envelope.getDeliveryTag());
// System.out.println("配置信息:" + properties);
System.out.println("消息" + new String(body));
System.out.println("阿里收到了哪些消息.....");
}
};
channel.basicConsume(aliBaba, true, consumer);
}
}
消费者2
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerRouter1 {
public static void main(String[] args) throws IOException, TimeoutException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置参数
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setVirtualHost("/itcast");
factory.setUsername("wujian");
factory.setPassword("wujian");
//创建连接
Connection connection =factory.newConnection();
Channel channel =connection.createChannel();
String microsoft = "microsoft_direct_log";
// 创建 queue
DefaultConsumer consumer = new DefaultConsumer(channel) {
// 这个是一个回调方法,当收到消息之后会自动执行该方法
/****
* consumerTag 标识 编号
* envelope 获取一些信息例如交换机 key,路由
* properties 配置信息
* body 数据
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
// System.out.println("标识:" + consumerTag);
// System.out.println("一些信息" + envelope.getExchange());
// System.out.println("这个是路由,其实是队列名称" + envelope.getRoutingKey());
// System.out.println("消息序号" + envelope.getDeliveryTag());
// System.out.println("配置信息:" + properties);
System.out.println("消息" + new String(body));
System.out.println("微软收到了哪些消息.....");
}
};
channel.basicConsume(microsoft, true, consumer);
}
}
演示结果
因为我的routing key 为 info 所以就只有microsoft_direct_log 队列收到消息
总结
Routing模式要求队列在绑定交换机时要指定routing key,消息会转发到符合routing key的队列