Rabbit MQ 客户端 API 开发
项目开始
第一步首先需要引入对应的 jar 包
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
连接 RabbitMQ
连接 RabbitMQ 有两种方式:1.根据特定参数连接 2.根据 URI 连接
根据特定的参数连接(用户名、密码、IP 地址、虚拟 broker、端口号)
// 声明连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 使用连接工厂赋值 userName、password、host、vHost、port 等等
factory.setUsername("userName");
factory.setPassword("password");
factory.setHost("host");
factory.setVirtualHost("vhost");
factory.setPort(5672);
// 创建连接
Connection conn = factory.newConnection();
根据 URI 连接也可以选择使用 URI 的方式来实现
ConnectionFactory factory = new ConnectionFactory();
factory.setUri("amqp://userName:password@host:port/vhost");
Connection connection = factory.newConnection();
System.out.println(connection);
connection.close();
Connection 可以用来创建多个 Channel 实例,但是 Channel 实例不能在线程间共享,应该为每一个线程开辟一个 Channel。线程共享会导致在网络上出现错误的通信帧交错,同时也会影响发送方确认机制的运行,所以多线程间共享 Channel 实例是非线程安全的。
使用队列和交换器
如何声明一个队列和交换器
Channel channel = connection.createChannel();
channel.exchangeDeclare("exchangeName", "direct", true);
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "exchangeName", "routuingKey");
上面创建了一个持久化的、非自动删除的、绑定类型为 direct 的交换器,同时也创建了一个非持久化的、排他的、自动删除的队列(此队列的名称由 RabbitMQ 自动生成)。
exchangeDeclare 方法详解
exchangeDeclare 有多个重载方法都是由下面的这个方法中参数的缺省构成的。
public DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) throws IOException;
此方法的返回值是 Exchange.DeclareOk 用来标识成功声明了一个交换器。
参数说明
1.exchange: 交换器的名称。
2.type: 交换器的类型。
3.durable: 设置是否持久化。true 表示持久化 false 表示非持久化。持久化可以将交换器存盘,在服务器重启的时候不会丢失相关信息。
4.autoDelete: 设置是否自动删除。true 表示自动删除。自动删除的前提是至少有一个队列或者交换器与这个交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑。注意不能错误地把这个参数理解为: “当与此交换器连接的客户端都断开时,RabbitMQ 会自动删除本交换器”。
5.internal: 设置是否是内置的。true 则表示内置交换器,客户端程序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器这种方式。
6.arguments: 其他一些结构化参数。比如 alternate-exchange。
有声明创建交换器的方法,也对应肯定也有删除交换器的方法。其中 exchange 表示交换器的名称,而 ifUnuserd 用来设置在交换器没有被使用的情况下删除,如果设置为 true,则只有再此交换器没有被使用的情况下才会被删除,如果设置为 false,则无论如何这个交换器都要被删除。
public AMQP.Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException;
public AMQP.Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException;
不带任何参数的 queueDeclare 方法默认创建一个由 RabbitMQ 命名的名称,这种队列也称匿名队列,拥有排他、自动删除、非持久化的属性。
queueDeclare 方法详解
public AMQP.Queue.DeclareOk queueDeclare() throws IOException;
public AMQP.Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) throws IOException;
不带任何参数的 queueDeclare 方法默认创建一个由 RabbitMQ 命名的名称,这种队列也称匿名队列,拥有排他、自动删除、非持久化的属性。
参数说明:
1.queue: 队列的名称。
2.durable: 设置是否持久化。true 表示持久化 false 表示非持久化。
3.exclusive: 设置是否排他。true 表示为排他,如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。
3.1.排他队列是基于连接(Connection)可见的。同一个连接的不同信道(Channel)是可以同时访问同一连接创建的排他队列;
3.2."首次"是指如果一个连接己经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同:
3.3.即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除,这种队列适用于一个客户端同时发送和读取消息的应用场景。
4.autoDelete: 设置是否自动删除。true 表示设置为自动删除。
4.1.自动删除的前提是:至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。不能把这个参数错误地理解为:“当连接到此队列的所有客户端断开时,这个队列自动删除”,因为生产者客户端创建这个队列,或者没有消费者客户端与这个队列连接时,都不会自动删除这个队列。
5.arguments: 设置队列的其他一些参数。如 x-rnessage-ttl 、x-expires 、x -rnax-length 、x-rnax-length-bytes 、x-dead-letter-exchange 、x-deadletter-routing-key, x-rnax-priority 等。
与交换器对应,关于队列也有删除的相应方法。其中 queue 表示队列名称,而 ifUnuserd 用来设置在队列没有被使用的情况下删除,如果设置为 true,则只有再此队列没有被使用的情况下才会被删除,如果设置为 false,则无论如何这个队列都要被删除。ifEmpty 设置为 true 表示在队列为空(队列里面没有任何消息堆积)的情况下才能够删除。
public AMQP.Queue.DeleteOk queueDelete(String queue) throws IOException;
public AMQP.Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) throws IOException;
还有一个方法用来清空队列中的内容,而不删除队列本身。
public AMQP.Queue.PurgeOk queuePurge(String queue) throws IOException;
exchangeBind 方法详解
除了可以将交换器和队列绑定,还可以将交换器与交换器绑定,绑定方法如出一辙。
public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey) throws IOException;
public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOException;
参数说明:
1.destination: 需要被绑定的交换器或队列
2.source: 需要绑定的交换器或队列。
3.routingKey: 路由键。
4.其他一些结构化参数。
发送消息
Channel.basicPublish 方法是发送消息。
String message = "Hello Word!";
channel.basicPublish("exchangeName", "routingKey", null, message.getBytes());
方法概览
public void basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body) throws IOException;
public void basicPublish(String exchange, String routingKey, boolean mandatory, AMQP.BasicProperties props, byte[] body) throws IOException;
public void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, AMQP.BasicProperties props, byte[] body) throws IOException;
参数说明:
1.exchange: 交换器的名称,指明消息需要发送到哪个交换器中。如果设置为空串。则消息会被发送到 RabbitMQ 默认的交换器中。
2.routhingKey: 路由键,交换器根据路由键将消息存储到相应的队列之中。
3.props: 消息的基本属性集。其包含 14 个属性成员,分别有 contentType、content Encoding、headers(Map<String, Object>)、deliveryMode、priority、correlationld、replyTo、expiration、messageld、timestamp、type、userld、appld、clusterld。
4.body: 消息体需要发送的消息。
5.mandatory: true 表示如果交换器根据路由键无法找到符合条件的队列时会将消息返回给生产者 false 时将消息直接丢弃。
6.immediate: true 表示交换器将消息路由到队列发现并不存在消费者时那么此消息不会被放入队列。
消费消息
RabbitMQ 消息模式分两种: 推 Push 模式和拉 Pull 模式。推模式采用 Basic.Consume 进行消费,而拉则是调用 Basic.Get 进行消费。我们只介绍推模式,对拉模式感兴趣可自行研究。
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicQos(1);
DeliverCallback deliverCallback = new DeliverCallback() {
@Override public void handle(String s, Delivery delivery) throws IOException {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("RabbitMqWorkRec1Test Received: " + message);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
};
channel.basicConsume(QUEUE_NAME, false, deliverCallback, new CancelCallback() {
@Override public void handle(String s) throws IOException {
System.out.println("RabbitMqWorkRec1Test CancelCallback==========> " + s);
}
});
以上代码中显式的 ack 操作对于消费者来说是非常必要的,可以防止必须要的消息丢失。
方法概览
public String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;
public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, Consumer callback) throws IOException;
参数说明:
1.queue: 队列名称。
2.autoAck: 设置是否自动确认。true 表示不自动确认,建议设置为 false。
3.consumerTag: 消费者标签,用来区分多个消费者。
4.noLocal: 设置为 true 表示不能将一个连接中生产者发送的消息传给这个连接的消费者。
5.exclusive: 设置是否排他。
6.arguments: 设置消费者的其他参数。
7.callback: 设置消费者的回调函数。用来处理 RabbitMQ 推送过来的消息。
Demo 示例
最后看来下完整的生产消费者示例。
生产者
public class RabbitMqPubTest {
private static final String EXCHANGE_NAME = "test_exchange_fanout";
public static void main(String[] args) {
Connection conn = null;
Channel channel = null;
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("userName");
factory.setPassword("password");
factory.setHost("host");
factory.setVirtualHost("vhost");
factory.setPort(5672);
conn = factory.newConnection();
channel = conn.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String message = "Hello Word!";
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
System.out.println("RabbitMqPubTest send: " + message);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != channel) {
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (null != conn) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
消费者
public class RabbitMqSub01Test {
private static final String EXCHANGE_NAME = "test_exchange_fanout";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("userName");
factory.setPassword("password");
factory.setHost("host");
factory.setVirtualHost("vhost");
factory.setPort(5672);
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
System.out.println("RabbitMqSub01Test queueName: " + queueName);
channel.queueBind(queueName, EXCHANGE_NAME, "");
DeliverCallback deliverCallback = new DeliverCallback() {
@Override public void handle(String s, Delivery delivery) throws IOException {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println("RabbitMqSub01Test Received: " + message);
}
};
channel.basicConsume(queueName, true, deliverCallback, new CancelCallback() {
@Override public void handle(String s) throws IOException {
}
});
}
}
public class RabbitMqSub02Test {
private static final String EXCHANGE_NAME = "test_exchange_fanout";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("userName");
factory.setPassword("password");
factory.setHost("host");
factory.setVirtualHost("vhost");
factory.setPort(5672);
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
System.out.println("RabbitMqSub02Test queueName: " + queueName);
channel.queueBind(queueName, EXCHANGE_NAME, "");
DeliverCallback deliverCallback = new DeliverCallback() {
@Override public void handle(String s, Delivery delivery) throws IOException {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println("RabbitMqSub02Test Received: " + message);
}
};
channel.basicConsume(queueName, true, deliverCallback, new CancelCallback() {
@Override public void handle(String s) throws IOException {
}
});
}
}
以上是 java 常用 rabbitMQ API 操作,感谢观看!不足之处请评论!
Rabbit MQ 客户端 API 开发的更多相关文章
- Rabbit MQ 客户端 API 进阶
之前说了一些基础的概念及使用方法,比如创建交换器.队列和绑定关系等.现在我们再来补充一下细节性的东西. 备份交换器 通过声明交换器的时候添加 alternate-exchange 参数来实现. Con ...
- Rabbit MQ 学习参考
网上的教程虽然多,但是提供demo的比较少,或者没有详细的说明,因此,本人就照着网上的教程做了几个demo,并把代码托管在码云,供有需要的参考. 项目地址:https://gitee.com/dhcl ...
- celery rabbit mq 详解
Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, ...
- Spring Boot:使用Rabbit MQ消息队列
综合概述 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程则可以 ...
- Spring boot集成Rabbit MQ使用初体验
Spring boot集成Rabbit MQ使用初体验 1.rabbit mq基本特性 首先介绍一下rabbitMQ的几个特性 Asynchronous Messaging Supports mult ...
- 使用Rabbit MQ消息队列
使用Rabbit MQ消息队列 综合概述 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息 ...
- 在 Windows 上安装Rabbit MQ 指南
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...
- (转)在 Windows 上安装Rabbit MQ 指南
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...
- Rabbit MQ 消息确认和持久化机制
一:确认种类 RabbitMQ的消息确认有两种.一种是消息发送确认,用来确认生产者将消息发送给交换器,交换器传递给队列的过程中消息是否成功投递.发送确认分为两步,一是确认是否到达交换器,二是确认是否到 ...
随机推荐
- SQL server 数据库安装
一.安装 1.点击setup双击 2.选择第一条-安装一个新的SQLserver 3.一路点击next 4.product Key-选择第一个:试用版 5.setup Role-选择所有 6.sell ...
- CentOS6.8搭建LNMP环境
selinux可能会致使编译安装失败,我们先禁用它.永久禁用,需要重启生效 sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/g’ /etc/selinux/c ...
- could not stop cortex-m device
检查一下STM32复位管脚是不是0V,如果是0V的话并且你有上拉电阻,那么就断电后检查一下STM32的VCC和GND是否短路,我的就是两个贴片电容击穿造成的短路从而使RST无法拉高.
- Codeforces 743C - Vladik and fractions (构造)
Codeforces Round #384 (Div. 2) 题目链接:Vladik and fractions Vladik and Chloe decided to determine who o ...
- LeetCode 分隔链表
题目链接:https://leetcode-cn.com/problems/partition-list/ 题目大意 略. 分析 空间复杂度 O(1) 的做法蛮有意思的,另外加头结点可以少写很多代码. ...
- FVWM_SMALLEST_CONFIG
... # ----------------------------------------------------------------- # HANDBOOK: # http://yaoqian ...
- cesium相关学习网址
cesium相关学习网址: cesium资料大全网址:https://www.cnblogs.com/cesium1/p/10062942.html http://192.168.101. ...
- Lambda表达式底层分析
一.我们先看下C#代码下Lamdba表达式的写法 // <summary> /// 写入日志委托 /// </summary> /// <param name=" ...
- 2019秋第一次Java学习总结
本周Java学习总结: 知识点总结: 1.Java中程序的执行步骤 使用Javac将一个.Java源文件编译成.class文件 使用Java可以执行一个*.class文件 2.&&与& ...
- 关于js的地址跳转
一.基本的地址跳转 解说: window.open 弹出新窗口的命令: page.html' 弹出窗口的文件名: 'newwindow' 弹出窗口的名字(不是文件名),非必须,可用空'代 ...