【RabbitMQ】快速入门

文章目录

  • [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();
    }
}
相关推荐
ch.ju2 小时前
Java程序设计(第3版)第二章——类型转换(1)
java
XiYang-DING2 小时前
【Java】哈希
java·哈希算法·散列表
想你依然心痛2 小时前
HarmonyOS 5.0医疗健康开发实战:构建分布式健康监测与AI预警系统
人工智能·分布式·harmonyos
ai旅人2 小时前
Guava RateLimiter深度解析:非阻塞令牌桶限流原理与跑批实战
java·限流·guava
Seven972 小时前
【从0到1构建一个ClaudeAgent】规划与协调-技能
java
范什么特西2 小时前
MyEclipse8.5配置
java·ide·myeclipse
想带你从多云到转晴2 小时前
05、数据结构与算法---栈与队列
java·数据结构·算法
QuZero2 小时前
ReentrantLock principle
java·算法
zjshuster2 小时前
流程引擎(Process Engine)简介
java·数据库·servlet