前言:大家好,我是小威,24届毕业生,曾经在某央企公司实习,目前在某税务公司。前面已经记录了两种消息模型知识,因此本篇文章将记录和分享剩下的RabbitMQ几种消息模型相关知识点。
本篇文章记录的基础知识,适合在学Java的小白,也适合复习中,面试中的大佬🤩🤩。
如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。
小威在此先感谢各位大佬啦~~🤞🤞
🏠个人主页:小威要向诸佬学习呀
🧑个人简介:大家好,我是小威,一个想要与大家共同进步的男人😉😉
目前状况🎉:24届毕业生,曾经在某央企公司实习,目前在某税务公司实习👏👏💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,我亲爱的大佬😘
以下正文开始
文章目录
- FanoutExchange广播模型
- DirectExchange定向模型
- TopicExchange主题模型
FanoutExchange广播模型
Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue。
Fanout Exchange不需要配置RoutingKey路由键,同时发布到FanoutExchange交换机上的消息都会被转发到与此交换机绑定的队列上。
以一个小例子来解释:首先在consumer消费者模块中,声明一个交换机(fanoutExchange)和两个队列(fanoutQueue1,fanoutQueue2),并将两个队列绑定到交换机上,同时添加相应的注解,交给spring容器管理bean。
在消费者模块,编写两个消费者方法,分别监听两个队列:
package cn.itcast.mq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FanoutConfig {
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("xiaowei.fanout");// 新建交换机xiaowei.fanout
}
@Bean //使用bean注解,交给spring容器处理
public Queue fanoutQueue1(){ //方法名为唯一id
return new Queue("fanout.queue1");
}
@Bean
//将队列1绑定到fanoutExchange交换机上
public Binding fanoutBinding1(Queue fanoutQueue1,FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue1)
.to(fanoutExchange);
}
@Bean
public Queue fanoutQueue2(){
return new Queue("fanout.queue2");
}
@Bean
//将队列2绑定到fanoutExchange交换机上
public Binding fanoutBinding2(Queue fanoutQueue2,FanoutExchange fanoutExchange){
return BindingBuilder
.bind(fanoutQueue2)
.to(fanoutExchange);
}
}
编写代码完成后运行消费者模块,刷新RabbitMQ网页可看到两个队列已经生成:
查看fanoutExchange交换机详情,可以看到fanoutQueue1和fanoutQueue2哥俩已经与该交换机绑定了:
接着在生产者模块中编写方法,向上面定义的交换机中发送消息:
@Test
public void testSendFanoutExchange(){
String exchangeName="xiaowei.fanout";//上面定义的交换机名称
String message="hello,evertone!";//发送的信息
rabbitTemplate.convertAndSend(exchangeName,"",message);//中间变量为路由键,此时设置为空字符串
}
运行测试方法,可以看到控制台打印的日志:
从上述结果可以看出,FanoutExchange交换机就像广播一样,不配置路由键,会将消息发送给所有与之绑定的消息队列上。
DirectExchange定向模型
对于FanoutExchange交换机,我们了解到,可以讲消息发送到每一个与之绑定的队列上。有的时候,虽然我们队列与交换机绑定到了一起,但是我们是不想其他队列接收到消息的。
因此我们此时需要用到路由键(RoutingKey),在生产者发送消息的时候,我们需要向指定RoutingKey,消息才会被发送到指定的队列上。
举个小栗子,下面是消费者consumer部分代码,定义两个队列(direct.queue1和direct.queue2)和一个交换机(xiaowei.direct),使用注解的方式使得两个队列绑定到交换机上,并且两者的RoutingKey有所不同。
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue1")
,exchange = @Exchange(name = "xiaowei.direct",type = ExchangeTypes.DIRECT)
,key = {"red","blue"}
)) //direct.queue1的key为red和blue
public void listenDirectQueue1(String msg){
System.out.println("消费者1已经接收到direct.queue1的消息:[" + msg + "]");
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue2")
,exchange = @Exchange(name = "xiaowei.direct",type = ExchangeTypes.DIRECT)
,key = {"red","yellow"}
)) //direct.queue2的key为red和yellow
public void listenDirectQueue2(String msg){
System.out.println("消费者2已经接收到direct.queue2的消息:[" + msg + "]");
}
编写代码完成后,运行项目可以看到两个队列已经生成:
同时查看xiaowei.direct交换机,可以看到RoutingKey栏目中有与队列相对应的key:
编写生产者的相关测试代码,声明交换机名称为“xiaowei.direct”,同时消息发送到路由键为“blue”的队列上面:
@Test
public void testSendDirectExchange(){
String exchangeName="xiaowei.direct";
String message="hello,blue!";
rabbitTemplate.convertAndSend(exchangeName,"blue",message);//路由到key为blue的队列上面
}
运行项目,可以看到控制台中,消费者1会接收到交换机发送来的消息,因为只有消费者1的RoutingKey为blue。
将生产者的测试代码换成key为yellow时,由于队列2中有yellow的路由键,因此队列2可以接收到消息,如下图所示:
将生产者的测试代码换成key为red的情况,由于队列1和队列2都包含路由键key,因此队列1和队列2都能接收到消息。控制台输出结果如下图:
TopicExchange主题模型
Topic 主题模式可以实现发布与订阅模式和Routing路由模式的功能,Topic在配置的时候可以使用通配符,比较灵活。
所有发送到TopicExchange交换机上面的消息都会被转发到与RoutingKey相关的队列上。
通配符的使用规则:
“#” 字符表示匹配0个或多个单词;
“*” 字符表示匹配一个单词
首先还是在消费者中定义两队列(topic.queue1和topic.queue2)和一个交换机(xiaowei.topic),并通过注解的方式将队列绑定到交换机上,指定topic.queue1队列的key为“china.#”,表示可以匹配以china开头的key;指定topic.queue2队列的key为#.news,表示可以匹配以news为结尾的key。
举栗:
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name ="topic.queue1" ),
exchange=@Exchange(name = "xiaowei.topic",type = ExchangeTypes.TOPIC),
key = "china.#"
))
public void listenTopicQueue1(String msg){
System.out.println("消费者1已经接收到topic.queue2的消息:[" + msg + "]");
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "topic.queue2"),
exchange = @Exchange(name = "xiaowei.topic",type = ExchangeTypes.TOPIC),
key = "#.news"
))
public void listenTopicQueue2(String msg){
System.out.println("消费者2已经接收到topic.queue2的消息:[" + msg + "]");
}
运行项目可以看到生成了上述的两队列:
查看xiaowei.topic交换机,可看到两队列的绑定情况以及路由情况:
编写生产者的测试模块:
@Test
public void testSendTopicExchange(){
String exchangeName="xiaowei.topic";
String message="祝诸佬们2023更上一层楼";
rabbitTemplate.convertAndSend(exchangeName,"china.news",message);//两者都能匹配上
}
运行项目可以看到控制台输出结果:
改变生产者测试模块代码得:
@Test
public void testSendTopicExchange(){
String exchangeName="xiaowei.topic";
String message="2023小威还要向诸佬学习呀";
rabbitTemplate.convertAndSend(exchangeName,"china.strong",message);//只有以china为开头的队列1能匹配得上
}
本篇文章就先分享到这里了,后续会继续分享RabbitMQ其他更深入的知识,感谢大佬认真读完支持咯~
文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起讨论🍻
希望能和诸佬们一起努力,今后进入到心仪的公司
再次感谢各位小伙伴儿们的支持🤞