目录
六类工作队列模式
简单队列模式概念
maven项目构建
生产者生产消息
查看当前rabbitmq信息
► 运行producer类
消费者消费消息
► 运行consumer类
六类工作队列模式
▸ 简单队列模式:一个消息生产者,一个消息消费者,一个队列。也称为点对点模式
▸ 工作模式:一个消息生产者,一个交换器,一个消息队列,多个消费者。同样也称为点对点模式
▸ 发布/订阅模式:无选择接收消息,一个消息生产者,一个交换器,多个消息队列,多个消费者
▸ 路由模式:在发布/订阅模式的基础上,有选择的接收消息,通过 routing 路由进行匹配接收消息
▸ 主题模式:在发布/订阅模式的基础上,根据主题匹配进行筛选是否接收消息,比第四类更灵活。
▸ RPC模式:类模式是拥有请求/回复的。也就是有响应的,上面5种都没有。
简单队列模式概念
一个生产者 P 发送消息到队列 Q,一个消费者 C 接收 (1:1:1
maven项目构建
简单队列模式,使用最基本的maven项目构建演示
1. 创建maven项目,next 一直下一步进行构建。
2. 引入rabbitmq 的maven依赖
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.12.0</version>
</dependency>
</dependencies>
生产者生产消息
新建producer生产者类,用于生产消息到消息队列
// 所有的中间件技术都是基于TCP/IP协议基础之上构建新型的协议规范,只不过rabbitmq遵循的是amqp
public class Producer {
public static void main(String[] args) {
// 1.建立连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 基于TCP/IP协议自然而然需要端口、ip等,比如mysql,redis等中间件
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setUsername("wpf2");
factory.setPassword("123");
factory.setVirtualHost("test_host");
Connection connection = null;
Channel channel = null;
try {
// 2.通过连接工厂建立连接
connection = factory.newConnection("我的第一个RabbitMQ Demo");
// 3.通过连接建立通道
channel = connection.createChannel();
// 4.通过通道创建交换机,声明队列,绑定关系,路由key,发送消息,和接收消息
String queueName = "queue001";
/**
* @Params1 队列名称
* @Params2 是否持久化 true:持久化,该队列将在服务器重启后依然继续存在
* @Params3 是否独占队列 true:独占,仅限于此连接
* @Params4 自动删除(最后一条消息被消费完毕后,是否把队列自动删除)
* @Params5 队列的其他属性(构造参数)
*
* 面试题:所谓持久化即消息存盘,非持久化会存盘吗? 回答:会存盘,但会随着服务器宕机而丢失
*/
channel.queueDeclare(queueName, true, false ,false, null);
// 5.准备消息内容
String message = "你好 梅花十三!";
// 6.发送消息给队列
/** @param1:交换机 面试题:可以存在没有交换机的队列吗? 不可能,虽未指定但会存在默认的交换机
* @param2:队列,路由key
* @param3:消息的状态控制
* @param4:消息主题
*/
channel.basicPublish("", queueName, null, message.getBytes());
} catch (Exception e) {
e.printStackTrace();
}finally {
// 7.关闭通道
if(channel!=null && channel.isOpen()){
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 8.关闭连接
if(connection!=null){
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
☛ 关于以下连接工厂参数说明
// 1.IP地址,如果是本地用以下,如果是服务器,用服务器的IP
factory.setHost("127.0.0.1");
// 2.默认端口号,可通过配置文件进行修改,自行百度,rabbitmq启动失败,可能是端口号被占用
factory.setPort(5672);
// 3.用户名和密码是自主创建的,不懂的翻阅博文:RabbitMQ的角色分类和管理
factory.setUsername("wpf2");
factory.setPassword("123");
// 4.vhost之前博文有详解过,请翻阅:RabbitMQ的角色分类和管理
factory.setVirtualHost("test_host");
!! 注意:在运行producer类之前,我们先来看一下目前已存在的连接、交换机、队列信息!!
查看当前rabbitmq信息
图形化界面不知道如何进入的,请翻阅:《RabbitMQ的安装与卸载》里面有手把手详细教学
1. 连接信息
2. 通道信息
3. 交换机信息
4. 队列信息
►
试试运行刚刚创建的生产者类,看看会发生什么
1. 点击main函数运行
2. 运行完毕,打开图形化界面,可以看到消息已经到队列中去了,
!! 说明:如果想要查看连接和通道信息,可以进行debug模式断点一步步运行结合图形化界面查看,由于producer类运行完毕,就关闭了连接和通道,所以图形化界面里是没有的
消费者消费消息
新建consumer消费者类,用于从消息队列中消费消息
// 代码同生产者基本一致,差异在于第4-6步
public class Consumer {
public static void main(String[] args) {
// 1.建立连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setUsername("wpf2");
factory.setPassword("123");
factory.setVirtualHost("test_host");
Connection connection = null;
Channel channel = null;
try {
// 2.通过连接工厂建立连接
connection = factory.newConnection("我的第一个RabbitMQ Demo");
// 3.通过连接建立通道
channel = connection.createChannel();
// 4.消费消息
/** @param1:消费的队列名称
* @param2:是否自动应答 true:是,消息一旦被消费成功,消息则从队列中删除
* @param3:消息送达时的回调
* @param4:消费者被取消时的回调
*/
channel.basicConsume("queue001",true, new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
System.out.println("接收成功!消息内容:" + new String(message.getBody(), "UTF-8"));
}
}, new CancelCallback() {
public void handle(String consumerTag) throws IOException {
System.out.println("接收消息失败。。。。。");
}
});
} catch (Exception e) {
e.printStackTrace();
}finally {
// 7.关闭通道
if(channel!=null && channel.isOpen()){
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 8.关闭连接
if(connection!=null){
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
►
我们来查看下图形界面,消息的状态
关于声明队列的参数说明
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
Map<String, Object> arguments)
queue:queue的名称
exclusive:排他队列,如果一个队列被声明为排他队列,该队列仅对首次申明它的连接可见,并在连接断开时自动删除。这里需要注意三点:
- 排他队列是基于连接可见的,同一连接的不同信道是可以同时访问同一连接创建的排他队列
- “首次”,如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同;
- 即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除的,这种队列适用于一个客户端发送读取消息的应用场景。
autoDelete:自动删除,如果该队列没有任何订阅的消费者的话,该队列会被自动删除。这种队列适用于临时队列。