在介绍完RabbitMQ基本概念后,我们使用JAVA代码来模拟一套生产者和消费者的模型,Talk is cheap 直接上代码了。使用Java Client整合RabbitMQ需要在pom.xml中导入如下依赖
<dependency>
<groupId>com.rabbitmqgroupId>
<artifactId>amqp-clientartifactId>
<version>5.0.0version>
dependency>
本系列博客源码GIT地址:https://github.com/RobertoHuang/RGP-RABBITMQ.git
1.创建连接工具类
public class ChannelUtils {
public static Channel getChannelInstance(String connectionDescription) {
try {
ConnectionFactory connectionFactory = getConnectionFactory();
Connection connection = connectionFactory.newConnection(connectionDescription);
return connection.createChannel();
} catch (Exception e) {
throw new RuntimeException("获取Channel连接失败");
}
}
private static ConnectionFactory getConnectionFactory() {
ConnectionFactory connectionFactory = new ConnectionFactory();
// 配置连接信息
connectionFactory.setHost("192.168.56.128");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("/");
connectionFactory.setUsername("roberto");
connectionFactory.setPassword("roberto");
// 网络异常自动连接恢复
connectionFactory.setAutomaticRecoveryEnabled(true);
// 每10秒尝试重试连接一次
connectionFactory.setNetworkRecoveryInterval(10000);
// 设置ConnectionFactory属性信息
Map connectionFactoryPropertiesMap = new HashMap();
connectionFactoryPropertiesMap.put("principal", "RobertoHuang");
connectionFactoryPropertiesMap.put("description", "RGP订单系统V2.0");
connectionFactoryPropertiesMap.put("emailAddress", "[email protected]");
connectionFactory.setClientProperties(connectionFactoryPropertiesMap);
return connectionFactory;
}
}
2.创建消息生产者
public class MessageProducer {
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = ChannelUtils.getChannelInstance("RGP订单系统消息生产者");
// 声明交换机 (交换机名, 交换机类型, 是否持久化, 是否自动删除, 是否是内部交换机, 交换机属性);
channel.exchangeDeclare("roberto.order", BuiltinExchangeType.DIRECT, true, false, false, new HashMap<>());
// 设置消息属性 发布消息 (交换机名, Routing key, 可靠消息相关属性 后续会介绍, 消息属性, 消息体);
AMQP.BasicProperties basicProperties = new AMQP.BasicProperties().builder().deliveryMode(2).contentType("UTF-8").build();
channel.basicPublish("roberto.order", "add", false, basicProperties, "订单信息".getBytes());
}
}
3.创建消息消费者
public class MessageConsumer {
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = ChannelUtils.getChannelInstance("RGP订单系统消息消费者");
// 声明队列 (队列名, 是否持久化, 是否排他, 是否自动删除, 队列属性);
AMQP.Queue.DeclareOk declareOk = channel.queueDeclare("roberto.order.add", true, false, false, new HashMap<>());
// 声明交换机 (交换机名, 交换机类型, 是否持久化, 是否自动删除, 是否是内部交换机, 交换机属性);
channel.exchangeDeclare("roberto.order", BuiltinExchangeType.DIRECT, true, false, false, new HashMap<>());
// 将队列Binding到交换机上 (队列名, 交换机名, Routing key, 绑定属性);
channel.queueBind(declareOk.getQueue(), "roberto.order", "add", new HashMap<>());
// 消费者订阅消息 监听如上声明的队列 (队列名, 是否自动应答(与消息可靠有关 后续会介绍), 消费者标签, 消费者)
channel.basicConsume(declareOk.getQueue(), true, "RGP订单系统ADD处理逻辑消费者", new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(consumerTag);
System.out.println(envelope.toString());
System.out.println(properties.toString());
System.out.println("消息内容:" + new String(body));
}
});
}
}
4.依次启动消息消费者和消息生产者,控制台打印
RGP订单系统ADD处理逻辑消费者
Envelope(deliveryTag=1, redeliver=false, exchange=roberto.order, routingKey=add)
#contentHeader<basic>(content-type=UTF-8, content-encoding=null, headers=null, delivery-mode=2, priority=null, correlation-id=null, reply-to=null, expiration=null, message-id=null, timestamp=null, type=null, user-id=null, app-id=null, cluster-id=null)
消息内容:订单信息
注意:初次运行时一定要先运行消费者后运行生产者,因为初次运行时还没有声明队列和交换机的绑定关系,如果先启动生产者会导致消息无法被正确路由而被丢弃
运行上诉代码后,打开RabbitMQ管理控制台界面看到配置如下
连接属性配置:
将管理控制台属性与上诉代码结合起来会更有利于读者理解每行代码的实际意义