SpringBoot整合RabbitMQ
SpringBoot整合RabbitMQ
建议把配置放到消费者:因为消费者是最先起来的服务。比如你想下订单,最好就是你下订单,马上就能给出正确反馈,这样消费者必须得时刻备着来处理订单。
fanout模式(订单案例)
- 依赖
<!--rabbitMQ依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 配置文件
# 配置rabbitmq服务
spring:
rabbitmq:
username: guest
password: guest
virtual-host: /
host: 192.168.181.200
port: 5672
- 配置类,写好交换机和队列的绑定关系
package com.xuexiangban.rabbitmq.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;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 17:34
*/
@Configuration
public class RabbitMqConfiguration {
//1. 声明注册fanout模式的交换机
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("fanout_order_exchange", true, false);
}
//2. 声明队列sms.fanout.queue; email.fanout.queue; duanxin.fanout.queue
@Bean
public Queue smsQueue(){
return new Queue("sms.fanout.queue", true);
}
@Bean
public Queue emailQueue(){
return new Queue("email.fanout.queue", true);
}
@Bean
public Queue duanxinQueue(){
return new Queue("duanxin.fanout.queue", true);
}
//3. 完成绑定关系(队列和交换机)
@Bean
public Binding smsBinding() {
return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
}
@Bean
public Binding emailBinding() {
return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
}
@Bean
public Binding duanxinBinding() {
return BindingBuilder.bind(duanxinQueue()).to(fanoutExchange());
}
}
- 生产者
package com.xuexiangban.rabbitmq.service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 17:22
*/
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* @Description: 模拟用户下单
* @return: void
*/
public void makeOrder(String userId,String productId,int num){
//1. 根据id查询库存是否充足
//2. 保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功:" + orderId);
//3. 通过MQ完成消息的分发
//(1)交换机 (2)路由key/queue队列名称 (3)消息内容
String exchangeName = "fanout_order_exchange";
String routingKey = "";
rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
}
}
- 消费者
消费者为另外的一个springboot模块
(1)先依赖后配置文件,记得端口要和上面的端口不一样
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
# 服务端口
server:
port: 8081
# 配置rabbitmq服务
spring:
rabbitmq:
username: guest
password: guest
virtual-host: /
host: 192.168.181.200
port: 5672
(2)消费者类
记得加@Component注解,交给SpringBoot管理
@RabbitListener(queues = {"duanxin.fanout.queue"}) :绑定队列,加在类上
@RabbitHandler :队列中接受到的消息传到下面的参数中,加在方法上
package com.xuexiangban.rabbitmq.service.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 22:32
*/
@RabbitListener(queues = {"duanxin.fanout.queue"})
@Component
public class FanoutDuanxinConsumer {
@RabbitHandler
public void reviceMessage(String message) {
System.out.println("duanxin fanout---接受到的消息是:" + message);
}
}
package com.xuexiangban.rabbitmq.service.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 22:32
*/
@RabbitListener(queues = {"email.fanout.queue"})
@Component
public class FanoutEmailConsumer {
@RabbitHandler
public void reviceMessage(String message) {
System.out.println("email fanout---接受到的消息是:" + message);
}
}
package com.xuexiangban.rabbitmq.service.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 22:32
*/
@RabbitListener(queues = {"sms.fanout.queue"})
@Component
public class FanoutSMSConsumer {
@RabbitHandler
public void reviceMessage(String message) {
System.out.println("sms fanout---接受到的消息是:" + message);
}
}
- 然后启动消费者启动类,就可以监听队列,然后消费了
package com.xuexiangban.rabbitmq;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootOrderRabbitmqConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootOrderRabbitmqConsumerApplication.class, args);
}
}
第二次提交了Direct模式(订单案例)
- 生产者
照比fanout模式,Direct多了个RoutingKey
配置类:交换机和队列的绑定关系(将FanoutExchange改为DirectExchange,并且绑定的时候BindingBuilder.bind(“队列”).to(“交换机”).with("RoutingKey");
多了一个with方法用于绑定RoutingKey)
package com.rabbitmq.springbootorderrabbitmqproducer.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 17:34
*/
@Configuration
public class DirectRabbitMqConfiguration {
//1. 声明注册direct模式的交换机
@Bean
public DirectExchange directExchange(){
return new DirectExchange("direct_order_exchange", true, false);
}
//2. 声明队列sms.direct.queue; email.direct.queue; duanxin.direct.queue
@Bean
public Queue directsmsQueue(){
return new Queue("sms.direct.queue", true);
}
@Bean
public Queue directemailQueue(){
return new Queue("email.direct.queue", true);
}
@Bean
public Queue directduanxinQueue(){
return new Queue("duanxin.direct.queue", true);
}
//3. 完成绑定关系(队列和交换机)
@Bean
public Binding directsmsBinding() {
return BindingBuilder.bind(directsmsQueue()).to(directExchange()).with("sms");
}
@Bean
public Binding directemailBinding() {
return BindingBuilder.bind(directemailQueue()).to(directExchange()).with("email");
}
@Bean
public Binding directduanxinBinding() {
return BindingBuilder.bind(directduanxinQueue()).to(directExchange()).with("duanxin");
}
}
Service方法:记得交换机的名字已经改变
/**
* @Description: 模拟用户下单
* @return: void
*/
public void makeOrderDirect(String userId,String productId,int num){
//1. 根据id查询库存是否充足
//2. 保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功:" + orderId);
//3. 通过MQ完成消息的分发
//(1)交换机 (2)路由key/queue队列名称 (3)消息内容
String exchangeName = "direct_order_exchange";
rabbitTemplate.convertAndSend(exchangeName, "sms", orderId);
rabbitTemplate.convertAndSend(exchangeName, "duanxin", orderId);
}
- 消费者:把队列名称改一下
@RabbitListener(queues = {"duanxin.direct.queue"})
@Component
public class DirectDuanxinConsumer {
@RabbitHandler
public void reviceMessage(String message) {
System.out.println("duanxin fanout---接受到的消息是:" + message);
}
}
- 如果先启动消费者,把第一步的绑定关系,也可以同时配置到生产者
package com.rabbitmq.springbootorderrabbitmqconsumer.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 17:34
*/
@Configuration
public class DirectRabbitMqConfiguration {
//1. 声明注册direct模式的交换机
@Bean
public DirectExchange directExchange(){
return new DirectExchange("direct_order_exchange", true, false);
}
//2. 声明队列sms.direct.queue; email.direct.queue; duanxin.direct.queue
@Bean
public Queue smsQueue(){
return new Queue("sms.direct.queue", true);
}
@Bean
public Queue emailQueue(){
return new Queue("email.direct.queue", true);
}
@Bean
public Queue duanxinQueue(){
return new Queue("duanxin.direct.queue", true);
}
//3. 完成绑定关系(队列和交换机)
@Bean
public Binding smsBinding() {
return BindingBuilder.bind(smsQueue()).to(directExchange()).with("sms");
}
@Bean
public Binding emailBinding() {
return BindingBuilder.bind(emailQueue()).to(directExchange()).with("email");
}
@Bean
public Binding duanxinBinding() {
return BindingBuilder.bind(duanxinQueue()).to(directExchange()).with("duanxin");
}
}
第三次提交了Topic模式(订单案例)
在消费者那里,利用注解的方式将交换机与队列进行绑定(推荐用配制文件方式)
- 生产者
public void makeOrderTopic(String s, String s1, int i) {
//1. 根据id查询库存是否充足
//2. 保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功:" + orderId);
//3. 通过MQ完成消息的分发
//(1)交换机 (2)路由key/queue队列名称 (3)消息内容
String exchangeName = "topic_order_exchange";
//sms:com.#
//email:*.email.#
//duanxin:#.duanxin.#
String routingKey = "com.email.duanxin";
rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
}
@Test
void testOrderTopic() {
orderService.makeOrderTopic("1","1",12);
}
- 消费者(注解配置队列交换机)
package com.rabbitmq.springbootorderrabbitmqconsumer.service.topic;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 22:32
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "duanxin.topic.queue", durable = "true", autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "#.sms.#"
))
@Component
public class TopicDuanxinConsumer {
@RabbitHandler
public void reviceMessage(String message) {
System.out.println("duanxin topic---接受到的消息是:" + message);
}
}
package com.rabbitmq.springbootorderrabbitmqconsumer.service.topic;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 22:32
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "email.topic.queue", durable = "true", autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "*.email.#"
))
@Component
public class TopicEmailConsumer {
@RabbitHandler
public void reviceMessage(String message) {
System.out.println("email topic---接受到的消息是:" + message);
}
}
package com.rabbitmq.springbootorderrabbitmqconsumer.service.topic;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 22:32
*/
@Component
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "sms.topic.queue", durable = "true", autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "com.#"
))
public class TopicSMSConsumer {
@RabbitHandler
public void reviceMessage(String message) {
System.out.println("sms topic---接受到的消息是:" + message);
}
}
第四次提交了TTL队列以及消息过期时间
当两者都设置了过期时间,已过期时间短者为标准。
- 生产者(队列)
package com.rabbitmq.springbootorderrabbitmqproducer.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author Pillar
* @version 1.0
* @date 2022/9/1 17:34
*/
@Configuration
public class TTLRabbitMqConfiguration {
@Bean
public DirectExchange TTLdirectExchange(){
return new DirectExchange("ttl_direct_exchange", true, false);
}
@Bean
public Queue ttlQueue(){
//设置过期时间
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 5000);
return new Queue("ttl.direct.queue", true,false,false,args);
}
@Bean
public Binding ttlBinding() {
return BindingBuilder.bind(ttlQueue()).to(TTLdirectExchange()).with("ttl");
}
}
public void makeOrderTtl(String s, String s1, int i) {
//1. 根据id查询库存是否充足
//2. 保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功:" + orderId);
//3. 通过MQ完成消息的分发
//(1)交换机 (2)路由key/queue队列名称 (3)消息内容
String exchangeName = "ttl_direct_exchange";
String routingKey = "ttl";
rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
}
@Test
void testOrderTtl() {
orderService.makeOrderTtl("1","1",12);
}
- 生产者(消息)
在生产者指定交换机和路由id,在配置个延时消息
public void makeOrderTtlMsg(String s, String s1, int i) {
//1. 根据id查询库存是否充足
//2. 保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功:" + orderId);
//3. 通过MQ完成消息的分发
//(1)交换机 (2)路由key/queue队列名称 (3)消息内容
String exchangeName = "ttl_direct_exchange";
String routingKey = "ttlmessage";
//给消息设置过期时间
MessagePostProcessor messagePostProcessor = new MessagePostProcessor(){
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration("5000");
message.getMessageProperties().setContentEncoding("UTF-8");
return message;
}
};
rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId,messagePostProcessor);
}
绑定交换机和普通队列
@Bean
public Binding ttlMsgBinding() {
return BindingBuilder.bind(ttlMessageQueue()).to(TTLdirectExchange()).with("ttlmessage");
}
测试
@Test
void testOrderTtlMsg() {
orderService.makeOrderTtlMsg("1","1",12);
}
总结
生产者,
先写配置类,写好交换机和队列的绑定关系
再写Service方法,指定好交换机的名称以及队列名,用到
rabbitTemplate.convertAndSend(交换机, 队列名, 消息);
消费者,
写好消费者类,
@RabbitListener(queues = {"**.queue"})
指定消费的队列名,用@RabbitHandler
放在方法上,消息会传递给给方法的参数上
本文来自博客园,作者:NeverLateThanBetter,转载请注明原文链接:https://www.cnblogs.com/do-it-520/p/16651226.html
韶华易逝,不能虚度年华。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器