文章目录
- [1. 引入依赖](#1. 引入依赖)
- [2. 生产者代码编写](#2. 生产者代码编写)
-
- [2.1 创建连接](#2.1 创建连接)
- [2.2 创建 Channel](#2.2 创建 Channel)
- [2.3 声明 Exchanges](#2.3 声明 Exchanges)
- [2.4 声明一个队列 Queue](#2.4 声明一个队列 Queue)
- [2.5 发送消息](#2.5 发送消息)
- [2.6 释放资源](#2.6 释放资源)
- [2.7 运行代码](#2.7 运行代码)
- [3. 消费者代码编写](#3. 消费者代码编写)
-
- [3.1 消费当前队列](#3.1 消费当前队列)
- [3.2 释放资源](#3.2 释放资源)
- [3.3 运行代码](#3.3 运行代码)
- [4 完整代码](#4 完整代码)
现在服务器上启动 RabbitMQ 服务
bash
systemctl start rabbitmq-server.service
1. 引入依赖
打开 IDEA 创建一个 Maven 项目

然后访问 Maven 仓库,去搜索【amqp-client】,选择第一个

然后选择比较稳定的,且使用人数较多的版本,比如:【5.20.0】

然后复制依赖,并粘贴到 IDEA 中的 pom.xml 文件里面去

或者直接复制下面的即可
xml
<!-- Source: https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.20.0</version>
<scope>compile</scope>
</dependency>
然后刷新 Maven 即可

2. 生产者代码编写
新建一个 ProduceDemo.java 文件

2.1 创建连接
💡 RabbitMQ 默认的用于客户端连接的 TCP 端口号是 5672,需要提前进行开放。
代码如下所示:
java
// 1. 建立连接
ConnectionFactory factory = new ConnectionFactory();
// 2. 设置参数
factory.setHost("8.156.77.78"); // MQ所在的服务器地址
factory.setPort(5672); // 端口号
factory.setUsername("edison"); // 账号
factory.setPassword("edison"); // 密码
factory.setVirtualHost("my_app_vhost"); // 虚拟主机
// 3. 创建连接connection
Connection connection = factory.newConnection();
但是这里会提示你进行抛异常处理

我们直接在外面进行声明即可,这样就不用写 try catch 了

记得给 edison 用户添加虚拟机的操作权限

2.2 创建 Channel
💡 生产者和消费者创建的 channel 并不是同一个。
代码如下所示:
java
// 4. 创建 channel 通道
Channel channel = connection.createChannel();
2.3 声明 Exchanges
RabbitMQ 在进行创建的时候,已经默认给我们提供了交换机,所以这里不需要再额外的去声明了

2.4 声明一个队列 Queue
这里直接调用 queueDeclare 方法即可,它的参数如下所示:
java
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments);
1. queue:队列名称
2. durable:是否持久化。true-设置队列为持久化,持久化的队列会存盘,服务器重启之后,消息不丢失。
3. exclusive:
* 是否独占,只能有一个消费者监听队列
* 当Connection关闭时,是否删除队列
4. autoDelete:是否自动删除,当没有Consumer时,自动删除掉
5. arguments:一些参数
如果没有一个 my_queue 这样的一个队列,会自动创建,如果有,则不创建。
代码如下所示:
java
// 6. 声明队列
channel.queueDeclare("my_queue", true, false, false, null);
2.5 发送消息
当一个新的 RabbitMQ 节点启动时,它会预声明(declare)几个内置的交换机,内置交换机名称是空字符串("")。生产者发送的消息会根据队列名称直接路由到对应的队列。

例如:如果有一个名为 "my_queue" 的队列,生产者可以直接发送消息到 "my_queue" 队列,而消费者可以从 "my_queue" 队列中接收消息,而不需要关心交换机的存在。这种模式非常适合简单的应用场景,其中生产者和消费者之间的通信是一对一的。

这里直接调用 basicPublish 方法即可,它的参数如下所示:
java
basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body)
1.exchange:交换机名称,简单模式下,交换机会使用默认的""
2.routingKey:路由名称,routingKey = 队列名称
3.props:配置信息
4.body:发送消息的数据
注意:使用的是内置交换机,使用内置交换机时,routingKey 要和队列名称一样,才可路由到对应的队列上去
通过 channel 发送消息到队列中,代码如下所示:
java
// 7. 发送消息
String msg = "Hello rabbitmq!";
channel.basicPublish("", "my_queue", null, msg.getBytes());
System.out.println(msg + "消息发生成功");
2.6 释放资源
显式地关闭 Channel 是个好习惯,但这不是必须的,Connection 关闭的时候,Channel 也会被关闭。
代码如下所示:
java
// 8. 资源释放
channel.close();
connection.close();
2.7 运行代码
运行之前:可以看到此时没有一个队列

然后运行代码:

运行之后,队列中就已经有了 my_queue 这个队列的信息

然后点击队列名字 my_queue 即可查看详细信息

然后点击【Get messages】,可以看到此时队列中只有一条信息 "Hello rabbitmq!"

3. 消费者代码编写
消费者代码和生产者前 3 步都是一样的,第 4 步改为消费当前队列。
- 1、创建连接
- 2、创建Channel
- 3、声明一个队列Queue
- 4、消费消息
- 5、释放资源
新建一个 ConsumeDemo.java 文件
代码如下所示:
java
// 1. 建立连接
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("8.156.77.78");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("admin");
factory.setVirtualHost("my_app_vhost");
// 2. 设置参数
Connection connection = factory.newConnection();
// 4. 开启 channel 通道
Channel channel = connection.createChannel();
// 5. 声明一个队列Queue
channel.queueDeclare("my_queue", true, false, false, null);
为什么消费者需要声明队列?
因为消费者启动时,需要指定订阅的队列,如果当时队列不存在,消费者就会报错。
3.1 消费当前队列
这里直接调用 basicConsume 方法即可,它的参数如下所示:
java
basicConsume(String queue, boolean autoAck, Consumer callback)
参数:
1. queue:队列名称
2. autoAck:是否自动确认,消费者收到消息之后,自动和MQ确认
3. callback:回调对象
String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;
DefaultConsumer 是 RabbitMQ 提供的一个默认消费者,实现了 Consumer 接口。
而 Consumer 用于定义消息消费者的行为。当需要从 RabbitMQ 接收消息时,需要提供一个实现了 Consumer 接口的对象。
java
handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
handleDelivery 是从队列接收到消息时,会自动调用该方法。
在这个方法中,我们可以定义如何处理接收到的消息,例如打印消息内容、处理业务逻辑或者将消息存储到数据库等。
参数说明:
- consumerTag:消费者标签,通常是消费者在订阅队列时指定的。
- envelope:包含消息的封包信息,如队列名称、交换机等。
- properties:一些配置信息。
- body:消息的具体内容。
代码如下所示:
java
// 6. 消费消息
DefaultConsumer consumer = new DefaultConsumer(channel) {
/*
回调方法,当收到消息后,会自动执行该方法:
1. consumerTag:标识
2. envelope:获取一些信息,如交换机、路由key
3. properties:配置信息
4. body:数据
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//todo
System.out.println("接收到消息: " + new String(body));
}
};
channel.basicConsume("my_queue", true, consumer);
3.2 释放资源
代码如下所示:
java
//等待回调函数执行完毕之后,关闭资源
TimeUnit.SECONDS.sleep(5);
//7. 释放资源 消费者相当于是一个监听程序,不需要关闭资源
channel.close();
connection.close();
实际上消费者相当于是一个监听程序,不需要关闭资源。
3.3 运行代码
运行程序,我们刚才发送的消息,就收到了

然后我们修改生成者的代码:连续发生 10 条消息
java
// 7. 发送消息
for (int i = 0; i < 10; i++) {
String msg = "Hello rabbitmq! " + i;
channel.basicPublish("", "my_queue", null, msg.getBytes());
}
System.out.println("消息发生成功~~~");
然后运行生产者 ProduceDemo 的代码,如下所示:

然后我们去 web 网页端查看队列详情,可以看到此时已经有 10 条消息发送到队列里面去了

然后我们运行消费者代码,来接收消息

接收,我们再去队列里面查看详情,可以看到队列里面已经为空了

另外,当我把 ProduceDemo 和 ConsumeDemo 里面的释放资源的代码都注释掉以后,再去运行,可以在 web 端看到是有 2 个【connection】的,表示生产者和消费者各自的通道

4 完整代码
生产者代码
java
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 ProduceDemo {
public static void main(String[] args) throws IOException, TimeoutException {
// 1. 建立连接
ConnectionFactory factory = new ConnectionFactory();
// 2. 设置参数
factory.setHost("8.156.77.78"); // MQ所在的服务器地址
factory.setPort(5672); // 端口号
factory.setUsername("edison"); // 账号
factory.setPassword("edison"); // 密码
factory.setVirtualHost("my_app_vhost"); // 虚拟主机
// 3. 创建连接connection
Connection connection = factory.newConnection();
// 4. 开启 channel 通道
Channel channel = connection.createChannel();
// 5. 声明交换机(使用内置的交换机即可)
// 6. 声明队列
channel.queueDeclare("my_queue", true, false, false, null);
// 7. 发送消息
for (int i = 0; i < 10; i++) {
String msg = "Hello rabbitmq! " + i;
channel.basicPublish("", "my_queue", null, msg.getBytes());
}
System.out.println("消息发生成功~~~");
// 8. 资源释放
channel.close();
connection.close();
}
}
消费者代码
java
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ConsumeDemo {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
// 1. 建立连接
ConnectionFactory factory = new ConnectionFactory();
// 2. 设置参数
factory.setHost("8.156.77.78");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("admin");
factory.setVirtualHost("my_app_vhost");
// 3. 创建连接connection
Connection connection = factory.newConnection();
// 4. 开启 channel 通道
Channel channel = connection.createChannel();
// 5. 声明一个队列Queue
channel.queueDeclare("my_queue", true, false, false, null);
// 6. 消费消息
DefaultConsumer consumer = new DefaultConsumer(channel) {
/*
回调方法,当收到消息后,会自动执行该方法:
1. consumerTag:标识
2. envelope:获取一些信息,如交换机、路由key
3. properties:配置信息
4. body:数据
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//
System.out.println("接收到消息: " + new String(body));
}
};
channel.basicConsume("my_queue", true, consumer);
// 7. 释放资源
TimeUnit.SECONDS.sleep(5); // 等待回调函数执行完毕之后,关闭资源
channel.close();
connection.close();
}
}