RabbitMQ Routing 路由模式案例
说明: Routing 模式要求队列在绑定交换机时要指定 routing key,消息会转发到符合 routing key 的队列
1. 创建rabbitMQ的生产者
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;
/**
* 创建rabbitMQ的生产者
* Routing 路由模式 -- Routing 模式要求队列在绑定交换机时要指定 routing key,消息会转发到符合 routing key 的队列
*/
public class ProducerRouting {
public static void main(String[] args) throws IOException, TimeoutException {
// 1. 创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 2. 设置连接参数
factory.setHost("192.168.192.137"); // 设置ip地址,默认为localhost
factory.setPort(5672); // 设置端口,默认为5672
factory.setVirtualHost("/qmh"); // 设置连接的虚拟机,默认为/
factory.setUsername("qmh"); // 设置用户名,默认为guest
factory.setPassword("qmh"); // 设置密码,默认为guest
// 3. 创建连接
Connection connection = factory.newConnection();
// 4. 创建Channel
Channel channel = connection.createChannel();
/**
* 5. 创建交换机 exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments)
* exchange 交换机名称
* type 交换机类型
* -- DIRECT("direct") 定向,把消息交给符合指定routing key 的队列
* -- FANOUT("fanout") 广播,将消息交给所有绑定到交换机的队列
* -- TOPIC("topic") 通配符,把消息交给符合routing pattern(路由模式) 的队列
* -- HEADERS("headers") 参数匹配
* durable 是否持久化
* autoDelete 自动删除
* internal 内部使用,RabbitMQ原生语言Erlang内部使用插件,默认false
* arguments 参数
*/
String exchangeName = "test_direct";
channel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT,true,false,false,null);
/**
* 6. 创建队列 queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
* queue 队列名称,如果没有该队列,自动创建
* durable 是否持久化, 如果true,数据写进rabbitMQ的数据库中
* exclusive 1. 是否独占,只能有一个消费者监听该队列 2. 当Connection删除时,是否删除队列
* autoDelete 是否自动删除,当没有消费者时,自动删除
* arguments 参数
*/
String queueOneName = "test_direct_queue_one";
String queueTwoName = "test_direct_queue_two";
channel.queueDeclare(queueOneName,true,false,false,null);
channel.queueDeclare(queueTwoName,true,false,false,null);
/**
* 绑定队列和交换机 queueBind(String queue, String exchange, String routingKey)
* queue 队列名称
* exchange 交换机名称
* routingKey 路由键,绑定规则
* -- 如果交换机类型为fanout, routingKey设置为""
* -- 如果交换机类型为direct, 自定义消息的 RoutingKey
*/
channel.queueBind(queueOneName,exchangeName,"error");
channel.queueBind(queueTwoName,exchangeName,"error");
channel.queueBind(queueTwoName,exchangeName,"info");
channel.queueBind(queueTwoName,exchangeName,"warning");
/**
* 6. 发送消息 basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
* exchange 交换机名称,简单模式交换机默认为 ""
* routingKey 路由名称
* -- 简单模式下的路由名称和队列名称保持一致
* -- 如果交换机类型为fanout, routingKey设置为""
* -- 如果交换机类型为direct, 指定消息的 RoutingKey
* props 配置信息
* body 发送消息数据
*/
String body = "日志信息: qmh用户调用了... ! 日志级别: info";
String bodyCopy = "日志信息: qmh用户删除了一条信息... ! 日志级别: error";
channel.basicPublish(exchangeName,"info",null,body.getBytes());
channel.basicPublish(exchangeName,"error",null,bodyCopy.getBytes());
// 7. 释放资源
channel.close();
connection.close();
}
}
2. 创建rabbitMQ的消费者
- 消费者一号
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 创建rabbitMQ的消费者
*/
public class ConsumerRoutingOne {
public static void main(String[] args) throws IOException, TimeoutException {
// 1. 创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 2. 设置连接参数
factory.setHost("192.168.192.137"); // 设置ip地址,默认为localhost
factory.setPort(5672); // 设置端口,默认为5672
factory.setVirtualHost("/qmh"); // 设置连接的虚拟机,默认为/
factory.setUsername("qmh"); // 设置用户名,默认为guest
factory.setPassword("qmh"); // 设置密码,默认为guest
// 3. 创建连接
Connection connection = factory.newConnection();
// 4. 创建Channel
Channel channel = connection.createChannel();
/**
* 5. 获取对应的队列名称
*/
String queueOneName = "test_direct_queue_one";
/**
* 6. 接收消息 basicConsume(String queue, boolean autoAck, Consumer callback)
* queue 队列名称
* autoAck 是否自动确认,当消费者接收到信息后,自动确认
* callback 回调
*/
Consumer consumer = new DefaultConsumer(channel){
/**
* 回调方法,当收到消息后执行该方法
* @param consumerTag 消息标识
* @param envelope 获取信息,比如交换机信息,路由key...
* @param properties 配置信息
* @param body 数据
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("body:" + new String(body));
System.out.println("消费者一号已经接收信息,并且保存进数据库 ! ");
}
};
channel.basicConsume(queueOneName,true,consumer);
}
}
- 消费者二号
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 创建rabbitMQ的消费者
*/
public class ConsumerRoutingTwo {
public static void main(String[] args) throws IOException, TimeoutException {
// 1. 创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 2. 设置连接参数
factory.setHost("192.168.192.137"); // 设置ip地址,默认为localhost
factory.setPort(5672); // 设置端口,默认为5672
factory.setVirtualHost("/qmh"); // 设置连接的虚拟机,默认为/
factory.setUsername("qmh"); // 设置用户名,默认为guest
factory.setPassword("qmh"); // 设置密码,默认为guest
// 3. 创建连接
Connection connection = factory.newConnection();
// 4. 创建Channel
Channel channel = connection.createChannel();
/**
* 5. 获取对应的队列名称
*/
String queueOneName = "test_direct_queue_two";
/**
* 6. 接收消息 basicConsume(String queue, boolean autoAck, Consumer callback)
* queue 队列名称
* autoAck 是否自动确认,当消费者接收到信息后,自动确认
* callback 回调
*/
Consumer consumer = new DefaultConsumer(channel){
/**
* 回调方法,当收到消息后执行该方法
* @param consumerTag 消息标识
* @param envelope 获取信息,比如交换机信息,路由key...
* @param properties 配置信息
* @param body 数据
* @throws IOException
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("body:" + new String(body));
System.out.println("消费者一号已经接收信息 ! ");
}
};
channel.basicConsume(queueOneName,true,consumer);
}
}