努力只能及格,拼命才能优秀
自述
前段时间有点忙,所以断更了,接下来接着更新,RabbitMQ的第三个场景------订阅者(publish)/发布者(Subscribe)。
发布/订阅
工作队列背后的假设是每个人物都会交付给一个工作者,在该场景(发布/订阅)----我们将向多个消费者传递一条相同的信息,该模式则被称为"发布/订阅"。
RabbitMQ消息传递模型的核心思想:生产者永远不会直接向队列发送任何消息。实际上,很多时候,生产者甚至根本不知道消息是否会被传递到任何队列(针对该问题,后续文章会解决),相反,生产者应该将消息发送到交易所/交换机上,交易所一方面接收来自生产者发送的消息,另一方面将收到消息推送到队列中,交易所必须确切地知道如何处理它收到的消息。交易所应该附加到特定队列吗?它应该附加到许多队列中吗?其规则由交换类型定义。
发布/订阅模型分解
生产者将消息发送给交易所,交易所将接收到的消息在发送给已绑定的队列上,最终消费者会接收队列传递的消息。
临时队列/绑定
什么是临时队列?用完即丢,拿来即用,一旦与消费者断开连接的话,队列就会自动删除。
//自动生成成队列名称,非持久、独占、自动删除队列。
String queueName = channel.queueDeclare().getQueue();
持久队列:(即使将队列重启后,队列也依旧存在)
独占:(仅由一个连接使用,该链接关闭时候队列将被删除)
自动删除:(当最后一个消费者取消订阅时,删除至少有一个消费者的队列)
ExSend.java
/**
* exchange(交换)
* <p>
* RabbitMQ的核心模型概念:生产者永远不会直接向队列发送任何消息。实际上,
* 很多时候,生产者甚至根本不知道消息是否会被传递到任何队列
*
*/
public class ExSend {
//交换机名称
private static String EXCHANGE_NAME = "exchange_name1";
public static void main(String[] args) {
try {
//连接
Connection connection = ConnectionUtil.getConnection();
//管道/通道
Channel channel = connection.createChannel();
//交换机
//paramone:交换机名称,paramtwo:交换类型(扇出)
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
//消息
String msg = "该章节讲解发布者/订阅者以及它的使用方式";
//发布
//paramone:交换机名称 paramtwo:原队列名称,现已不需要填写
//paramthree:配置 paramfour:消息
channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes());
System.out.println("provider===消息发送成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
ExRecv.java
/**
* 消费者2
*/
public class ExRecv2 {
//交换机名称
private static String EXCHANGE_NAME = "exchange_name1";
public static void main(String[] args) {
try {
//连接
Connection connection = ConnectionUtil.getConnection();
//通道
Channel channel = connection.createChannel();
//创建交换机--如果存在则免创建
//paramone:交换机名称,paramtwo:交换类型(扇出)
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
//非持久、独占式、自动删除的队列
String queue = channel.queueDeclare().getQueue();
//绑定队列
//paramone:队列名称 paramtwo:交换机名称
channel.queueBind(queue, EXCHANGE_NAME, "");
//接收信息
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
System.out.println("consumer1====="+new String(delivery.getBody()));
}
};
//消费信息-到指定的队列中获取信息
//paramone:到指定队列中获取信息 paramtwo:ack响应 paramtrhee:回调
channel.basicConsume(queue, true, deliverCallback, ismepty -> {
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
ExRecv2.java
/**
* 消费者
*/
public class ExRecv {
//交换机名称
private static String EXCHANGE_NAME = "exchange_name1";
public static void main(String[] args) {
try {
//连接
Connection connection = ConnectionUtil.getConnection();
//通道
Channel channel = connection.createChannel();
//创建交换机--如果存在则免创建
//paramone:交换机名称,paramtwo:交换类型(扇出)
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
//非持久、独占式、自动删除的队列
String queue = channel.queueDeclare().getQueue();
//绑定队列
//paramone:队列名称 paramtwo:交换机名称
channel.queueBind(queue, EXCHANGE_NAME, "");
//接收信息
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
System.out.println("consumer2=====" +new String(delivery.getBody()));
}
};
//消费信息-到指定的队列中获取信息
//paramone:到指定队列中获取信息 paramtwo:ack响应 paramtrhee:回调
channel.basicConsume(queue, true, deliverCallback, ismepty -> {
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
效果图
Ending
可怜的访问量~~~~~访问量往上顶顶吧!!!