rabbitmq中直接路由模型属于发布-订阅模型中的一种,它是采用direct交换机,通过路由key精确匹配。
直接路由模型和主题路由模型非常相似,它们唯一区别在于:直接路由模型对于路由key是精确匹配的,而主题路由模型对于路由key是模糊匹配的(使用通配符 )。
示例代码
日志生产者 :发布了info、warning、error级别的消息各10条。
package com.tingcream.rabbitmq.routing;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class RoutingLogProducer {
private static String EXCHANGE_NAME="routing_logs";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
//主机 端口 vhost 用户名 密码
factory.setHost("192.168.9.102");
factory.setUsername("rabbitmq");
factory.setPassword("rabbitmq123");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setVirtualHost("/");
Connection connection=factory.newConnection();
Channel channel=connection.createChannel();
//info warning error
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
// channel.exchangeDeclare(exchange, type, durable, autoDelete, arguments)
for (int i=0;i<10;i++){
String message="你好,这是info级别消息 "+i;
channel.basicPublish(EXCHANGE_NAME,"info",null,message.getBytes());
System.out.println("RoutingLogProducer Send: " + message );
}
for (int i=0;i<10;i++){
String message="你好,这是warning级别消息 "+i;
channel.basicPublish(EXCHANGE_NAME,"warning",null,message.getBytes());
System.out.println("RoutingLogProducer Send: " + message );
}
for (int i=0;i<10;i++){
String message="你好,这是error级别消息 "+i;
channel.basicPublish(EXCHANGE_NAME,"error",null,message.getBytes());
System.out.println("RoutingLogProducer Send: " + message );
}
channel.close();
connection.close();
}
}
日志消费者A、B、C分别只消费info、warning、error级别的日志。
RoutingLogReceiverA.java
package com.tingcream.rabbitmq.routing;
import java.io.IOException;
import com.rabbitmq.client.AMQP;
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;
public class RoutingLogReceiverA {
private static String EXCHANGE_NAME="routing_logs";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
//主机 端口 vhost 用户名 密码
factory.setHost("192.168.9.102");
factory.setUsername("rabbitmq");
factory.setPassword("rabbitmq123");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setVirtualHost("/");
Connection connection=factory.newConnection();
Channel channel=connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
//获取一个随机的队列名称
String queueName = channel.queueDeclare().getQueue();
// channel.queueBind(queue, exchange, routingKey)
channel.queueBind(queueName, EXCHANGE_NAME, "info");
System.out.println("RoutingLogReceiverA Waiting for messages");
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( "RoutingLogReceiverA接收到消息:" + message );
}
};
channel.basicConsume(queueName, true, consumer);
}
}
RoutingLogReceiverB.java
package com.tingcream.rabbitmq.routing;
import java.io.IOException;
import com.rabbitmq.client.AMQP;
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;
public class RoutingLogReceiverB {
private static String EXCHANGE_NAME="routing_logs";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
//主机 端口 vhost 用户名 密码
factory.setHost("192.168.9.102");
factory.setUsername("rabbitmq");
factory.setPassword("rabbitmq123");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setVirtualHost("/");
Connection connection=factory.newConnection();
Channel channel=connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
//获取一个随机的队列名称
String queueName = channel.queueDeclare().getQueue();
// channel.queueBind(queue, exchange, routingKey)
channel.queueBind(queueName, EXCHANGE_NAME, "warning");
System.out.println("RoutingLogReceiverB Waiting for messages");
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( "RoutingLogReceiverB接收到消息:" + message );
}
};
channel.basicConsume(queueName, true, consumer);
}
}
RoutingLogReceiverC.java
package com.tingcream.rabbitmq.routing;
import java.io.IOException;
import com.rabbitmq.client.AMQP;
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;
public class RoutingLogReceiverC {
private static String EXCHANGE_NAME="routing_logs";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
//主机 端口 vhost 用户名 密码
factory.setHost("192.168.9.102");
factory.setUsername("rabbitmq");
factory.setPassword("rabbitmq123");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setVirtualHost("/");
Connection connection=factory.newConnection();
Channel channel=connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
//获取一个随机的队列名称
String queueName = channel.queueDeclare().getQueue();
// channel.queueBind(queue, exchange, routingKey)
channel.queueBind(queueName, EXCHANGE_NAME, "error");
System.out.println("RoutingLogReceiverC Waiting for messages");
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( "RoutingLogReceiverC接收到消息:" + message );
}
};
channel.basicConsume(queueName, true, consumer);
}
}
注:
日志消费者中,声明使用的交换机类型为direct,交换机名称为routing_logs(与生产者保持一致),queue的名称也是随机生成的。
但channel.queueBind(queueName, EXCHANGE_NAME, "info")代码中所绑定的路由key不同。消费者A、B、C分别绑定的路由key为info、warning和error 。
分别启动消费这A、B、C和生产者程序。
我们再看看管理后台,其中的queue标签栏中,又多出了一个交换机,这就是我们刚声明的一个direct类型的交换机,名叫routing_logs