声明:本示例的理论知识基于上一篇文章
SpringBoot使用RabbitMQ的准备工作:
声明:本人测试时,使用软硬件环境为:Windows7、Jdk1.8、Eclipse、rabbitmq-server-3.6.1、
SpringBoot 2.0.3.RELEASE。
第一步:在SpringBoot的pom.xml中引入AMQP高级消息队列协议的依赖。
注:消息生产者、消息消费者如果不在同一个项目(服务)中,那么都必须有此步骤。
注:这里可以不指定AMQP版本,SpringBoot会自动导入与该SpringBoot版本相搭配的AMQP的版本。
第二步:配置系统配置文件
给出文字版:
#------------------------------------SpringBoot 服务名、端口号 spring.application.name=rabbit-mq-producer server.port=8489
#------------------------------------RabbitMQ基本配置 # RabbitMQ的主机地址(默认为:localhost) spring.rabbitmq.host=localhost # 指定该用户要连接到的虚拟host端(注:如果不指定,那么默认虚拟host为“/”) spring.rabbitmq.virtual-host = /vhost_A # amqp协议端口号:5672; 集群端口号:25672;http端口号:15672; spring.rabbitmq.port=5672 # 登录到RabbitMQ的用户名、密码 spring.rabbitmq.username=JustryDeng spring.rabbitmq.password=xxxxxx
#------------------------------------RabbitMQ可选配置(注:这里只用到了特别少的几个) # broker端没有收到消费者的ACK(即:消费者异常时)时,是否再次向消费者投递消息(默认为false) # 为false时,如果没有收到消费者的ACK,那么会无限投递;设置为true时,默认投递时次数为3此 spring.rabbitmq.listener.simple.retry.enabled=true # 设置向消费者投递消息的最大次数 spring.rabbitmq.listener.simple.retry.max-attempts=2 # 投递消息的间隔(单位ms) spring.rabbitmq.listener.simple.retry.initial-interval=2000 |
注:消息消费者必须要有此步骤;如果消息生产者与消息消费者处于不同的项目或不同的服务等情况,那么消息生
产者也需要配置RabbitMQ的基本配置项;
注:如果消息生产者与消息消费者处于同一个项目或服务下(即:消息生产者与消息消费者共用同一个配置文件),
那么消息生产者就不需要再配置了;
注:更多关于RabbitMQ的配置,可详见https://blog.csdn.net/en_joker/article/details/80103519。
SpringBoot使用RabbitMQ示例:
声明:不管是以下的哪一种策略,如果一个消息的推送目标有多个Queue,那么这些Queue之间会进行竞争,最终该
消息只会被其中一个Queue消费。特别注意:如果同一个消息消费者在多处启动(即:Queue、Exchange等都一
样),那么也会发生竞争,最终该消息只会被其中某处的Queue消费。
Fanout策略:
目录结构:
Consumer:
QueueConfiguration.java配置类中的相关配置为:
FanoutExchangeAndBindingConfiguration.java配置类中的相关配置为:
DemoMessageListener中对应的消费消息的方法为:
Producer:
单元测试SimulationMessageProducerTest.java中的对应测试代码为:
注:当消息生产者与消息消费者处于不同的项目或不同的服务等时,那么消息生产者也需要配置RabbitMQ的基本配置项,来 定位到RabbitMQ Server。详见准备步骤里系统配置文件中的RabbitMQ的基本配置部分。
注:上图中的方法作用是:将Object对象转化为AMQP能发送的消息数据;三个参数分别是交换机名字、路由键、消息内容对象。
.convertAndSend(String exchangeName,String routingKey,Object obj)
提示:当不采用direct或topic策略时,没有路由键,那么对应路由键参数位置使用双引号即可。
提示:消息内容对象在内部会被转化为json字符串,并放入请求体中,最终传递到消息消费者中对应方法里面的;所以
接收参数时的注意事项和HttpClient使用Post传递参数,接收参数时要注意的事项一样。
运行单元测试,console的打印结果为:
Direct策略:
目录结构:
Consumer:
QueueConfiguration.java配置类中的相关配置为:
DirectExchangeAndBindingConfiguration.java配置类中的相关配置为:
DemoMessageListener中对应的消费消息的方法为:
Producer:
单元测试SimulationMessageProducerTest.java中的对应测试代码为:
注:当消息生产者与消息消费者处于不同的项目或不同的服务等时,那么消息生产者也需要配置RabbitMQ的基本配
置项,来定位到RabbitMQ Server。详见准备步骤里系统配置文件中的RabbitMQ的基本配置部分。
注:上图中的方法作用是:将Object对象转化为AMQP能发送的消息数据;三个参数分别是交换机名字、路由键、消息
内容对象。.convertAndSend(String exchangeName,String routingKey,Object obj)
提示:当不采用direct或topic策略时,没有路由键,那么对应路由键参数位置使用双引号即可。
注:convertAndSend()方法是被重载了的,看自己的情况使用不同参数的convertAndSend()方法即可。本示例中,
只示例如上图所示该方法。
运行单元测试,console的打印结果为:
Topic策略:
目录结构:
Consumer:
QueueConfiguration.java配置类中的相关配置为:
TopicExchangeAndBindingConfiguration.java配置类中的相关配置为:
注:*表示任意一个标识符;#表示零个或多个(也可以是1个)标识符。
注:*和#一般都只用于队列和交换机绑定时有效;消息生产者无法使用其表示通配(即:消息生产者使用时无效)。
DemoMessageListener中对应的消费消息的方法为:
Producer:
单元测试SimulationMessageProducerTest.java中的对应测试代码为:
注:当消息生产者与消息消费者处于不同的项目或不同的服务等时,那么消息生产者也需要配置RabbitMQ的基本
配置项,来定位到RabbitMQ Server。详见准备步骤里系统配置文件中的RabbitMQ的基本配置部分。
注:上图中的方法作用是:将Object对象转化为AMQP能发送的消息数据;三个参数分别是交换机名字、路由键、消息内容对象。
.convertAndSend(String exchangeName,String routingKey,Object obj)
提示:当不采用direct或topic策略时,没有路由键,那么对应路由键参数位置使用双引号即可。
提示:消息内容对象在内部会被转化为json字符串,并放入请求体中,最终传递到消息消费者中对应方法里面的;所以
接收参数时的注意事项和HttpClient使用Post传递参数,接收参数时要注意的事项一样。
注:convertAndSend()方法是被重载了的,看自己的情况使用不同参数的convertAndSend()方法即可。本示例中,只
示例如上图所示该方法。
运行单元测试,console的打印结果为:
单元测试topicExchangeTest1()的运行结果为
单元测试topicExchangeTest2()的运行结果为
单元测试topicExchangeTest3()的运行结果为
提示:如果输出结果与理想结果不一样;那么最好去MQ里,把原来与Queue绑定的Exchange删除,重新绑定Queue队
列到TopicExchange交换机并放入vhost里(原因分析:该交换机原来绑定的可能是没有通配路由键的Queue,
改成了路由键通配后,需要先删除vhost中原来的该交换机,再重新把绑定了通配路由键队列后的交换机放入
vhost里面)。
即:一旦将绑定了Queue的Exchange放入vhost后,那么该交换机对于其绑定了的Queue的“认知”就固定了;如
果想改变该交换机的认知,那么必须先删除该交换机,然后在放入有新“认知”的交换机。
追注:其他几种策略也一样,修改Queue与Exchange的绑定信息后,也最好去vhost中删除该交换机,再重新放
入新的交换机。
Headers策略:
目录结构:
Consumer:
QueueConfiguration.java配置类中的相关配置为:
HeadersExchangeAndBindingConfiguration.java配置类中的相关配置为:
注:headers中,可以存放很多用来验证身份的键值对,我们可以用All来指定:当消息生产者传到Exchange中的
headers中的键值对所有都符合(所有Map或所有Key)要求时,才启用该队列;或使用Any来指定:只要消息生
产者传到Exchange中的headers中的键值对有至少一个(至少一个Map或至少一个Key)符合要求时,就启用
该队列。
DemoMessageListener中对应的消费消息的方法为:
Producer:
单元测试SimulationMessageProducerTest.java中的对应测试代码为:
运行单元测试,console的打印结果为:
单元测试headersExchangeWhereAllMapTest()的运行结果为
单元测试headersExchangeWhereAnyMapTest()的运行结果为
提示:
- 本文只是对SpringBoot使用MQ的一个示例介绍;在实际运用时,方式方法注意事项等较多。
- 如果想传递对象,那么可以:消息生产者将对象转换为json字符串放入MQ,然后消息消费者接受json字符串后,转换为Java对象即可。