RabbitMQ(2)案列
一:RabbitMQ相当于一个信箱
我们只需要将收件人写下,放入到信箱中就不需要管了。自动送过去。
生产者:什么都不做,就是发消息
消息传递:消息队列:信箱的名字就叫做队列,队列接近无限大的缓冲,取决于硬盘有多大它就有多大。这个队列专门用来存储接收转发消息。
消费者:大部分在等待和接收消息的

ConnectionFactory factory=new ConnectionFactory();连接工厂
factory.setHost(“localhost”);连接RabbitMQ服务器()
factory.setVirtualHost(“/shop”);
factory.setUsername(“shop”);
factory.setPassword(“shop”);
Connection connection=factory.newConnection();通过连接工厂创建连接
Channel channel=connection.createChannel();通过连接创建信道
channel.queueDeclare(队列名,false,false,false,null);绑定队列
二:广播类型案列(广播类型的RabbitMQ)

P:发送端,X交换机,红的是队列,C是接收方
1.RabbitMQ客户端依赖
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
2.Send类发送端
从图中看到:
消息产生后不是直接投送到队列中,而是将消息先投送给Exchange交换机,然后消息经过Exchange
交换机投递到相关队列
多个消费者消费的不再是同一个队列,而是每个消费者消费属于自己的队列。
/**
* 发布与订阅模式队列-fanout广播模式-消息发送者
*/
public class Send {
// 队列名称
// 如果不声明队列,会使用默认值,RabbitMQ会创建一个排他队列,连接断开后自动删除
//private final static String QUEUE_NAME = "ps_fanout";
// 交换机名称
private static final String EXCHANGE_NAME = "exchange_fanout";7.2. Receiving
这里对于消费者,消费消息时,消息通过交换机Exchange被路由到指定队列,绑定队列到指定交换机来
实现,一个消费者接到消息后用于邮件发送模拟,另一消费者收到消息,用于短信发送模拟。
Recv01.java
public static void main(String[] args) {
// 创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setUsername("shop");
factory.setPassword("shop");
factory.setVirtualHost("/shop");
Connection connection = null;
Channel channel = null;
try {
// 通过工厂创建连接
connection = factory.newConnection();
// 获取通道
channel = connection.createChannel();
// 声明队列
//channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 绑定交换机 fanout:广播模式
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
// 创建消息,模拟发送手机号码和邮件地址
String message = "18600002222|12345@qq.com";
// 将产生的消息发送至交换机
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + message + "'");
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} finally {
try {
// 关闭通道
if (null != channel && channel.isOpen())
channel.close();
// 关闭连接
if (null != connection && connection.isOpen())
connection.close();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
生产者:之前绑定的是队列,现在绑定的是交换机。然后直接发送给交换机
3.Recv消费端
这里对于消费者,消费消息时,消息通过交换机Exchange被路由到指定队列,绑定队列到指定交换机来
实现,一个消费者接到消息后用于邮件发送模拟,另一消费者收到消息,用于短信发送模拟。
/**
* 发布与订阅模式队列-fanout广播模式-消息接收者
*/
public class Recv01 {
// 交换机名称
private static final String EXCHANGE_NAME = "exchange_fanout";
public static void main(String[] args) {
// 创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(5672);
factory.setUsername("shop");
factory.setPassword("shop");
factory.setVirtualHost("/shop");
try {
// 通过工厂创建连接
final Connection connection = factory.newConnection();
// 获取通道
final Channel channel = connection.createChannel();
// 绑定交换机 fanout:广播模式
channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
// 获取队列名称
String queueName = channel.queueDeclare().getQueue();
// 绑定队列
channel.queueBind(queueName, EXCHANGE_NAME, "");
/*
限制RabbitMQ只发不超过1条的消息给同一个消费者。
当消息处理完毕后,有了反馈,才会进行第二次发送。
*/
int prefetchCount = 1;
channel.basicQos(prefetchCount);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
// 获取消息,按|分割以后一个消费者发短信,一个消费者发邮件
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received01 '" + message + "'");
// 手动回执消息
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
// 监听队列
/*
autoAck = true代表自动确认消息
autoAck = false代表手动确认消息
*/
boolean autoAck = false;
channel.basicConsume(queueName, autoAck, deliverCallback, consumerTag -> {
});
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
}
将交换机和排他队列进行了绑定,最后绑定的是队列,和发送的区别:
总结
从结果可以看出生产者发送了一条消息,用于邮件发送和短信发送的消费者均可以收到消息进行后续
处理。
问题:生产者产生的消息所有消费者都可以消费,可不可以指定某些消费者消费呢?
解决:采用direct路由模式。
浙公网安备 33010602011771号