目录
- 环境配置
- pom
- yml
- 下单业务场景
- 订阅发布-配置代码producer
- 通过 RabbitMQConfig配置类 创建交换机Fanout、绑定队列
- 订阅发布-配置代码consumer
- 路由模式-配置代码producer
- 通过DirectRabbitMQConfig配置类 创建交换机Direct、绑定队列、设置RoutingKey
- 路由模式-配置代码consumer
- 主题模式-配置代码producer
- 主题模式-配置代码(注解)consumer
一、环境配置
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>henu.soft.xiaosi</groupId>
<artifactId>springboot-order-rabbitmq-producer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-order-rabbitmq-producer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
yml
server:
port: 8080
spring:
rabbitmq:
username: admin
password: admin
virtual-host: /
host: 127.0.0.1
port: 5672
二、业务场景下单
订单业务场景
- springboot-order-rabbitmq-producer 模拟生产者,模拟完成一个订单的保存后 生成一个orderId供后续三个业务消费。
- springboot-order-rabbitmq-consumer 模拟消费者,包含三个任务
1.订阅发布-配置代码producer
OrderService
package henu.soft.xiaosi.springbootorderrabbitmqproducer.service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 模拟用户下单
* @param userId
* @param productId
* @param num
*/
public void makeOrder(String userId,String productId,int num){
// 1. 根据商品订单id查询库存是否充足
// 2. 保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功" + orderId);
// 3. 通过消息队列完成消息的分发
// 需要he配置类名字保持一致
String exchangeName = "fanout_order_exchange";
String routingKey = "";
/**
* 参数
* 交换机
* 路由key、queue队列名称
* 消息内容
*/
// 关于交换机的生命、队列的声明、绑定需要写一个配置类
rabbitTemplate.convertAndSend(exchangeName,routingKey,orderId);
}
}
通过 RabbitMQConfig配置类 创建交换机Fanout、绑定队列
package henu.soft.xiaosi.springbootorderrabbitmqproducer.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 RabbitMQConfig {
// 1. 声明注册fanout模式的交换机
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("fanout_order_exchange",true,false);
}
// 2. 声明队列 sms.fanout.queue 、email.fanout.queue 、message.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 messageQueue(){
return new Queue("message.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 messageBinding(){
return BindingBuilder.bind(messageQueue()).to(fanoutExchange());
}
}
2.订阅发布-配置代码consumer
yml和pom文件同上,需要注意的是yml端口需要设置一下,三个服务类似,用email消费者举栗
@RabbitListener(queues = {"email.fanout.queue"})
用于绑定队列@RabbitHandler
用于声明消费方法
package henu.sofi.xiaosi.springbootorderconsumer.service;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
@RabbitListener(queues = {"email.fanout.queue"})
public class EmailService {
@RabbitHandler
public void receiveEmail(String id){
System.out.println("email fanout 消费了订单信息是:--》" + id);
}
}
启动测试,输出
email fanout 消费了订单信息是:--》5a229eda-da45-4f3b-b9e9-92c3184f6265
message fanout 消费了订单信息是:--》5a229eda-da45-4f3b-b9e9-92c3184f6265
sms fanout 消费了订单信息是:--》5a229eda-da45-4f3b-b9e9-92c3184f6265
2021-07-17 15:43:14.119 INFO 3772 --- [ main] s.x.s.SpringbootOrderConsumerApplication : Started SpringbootOrderConsumerApplication in 2.087 seconds (JVM running for 5.821)
email fanout 消费了订单信息是:--》615b1fe5-5332-42cd-86d7-099f85c96cf6
sms fanout 消费了订单信息是:--》615b1fe5-5332-42cd-86d7-099f85c96cf6
message fanout 消费了订单信息是:--》615b1fe5-5332-42cd-86d7-099f85c96cf6
3.路由模式-配置代码producer
上述订阅发布模式的基础上,将 声明交换机、队列、绑定队列的 配置类 修改
- 声明交换机的类型换为DirectExchange
- 绑定队列的时候后面
.with(此队列对应的routingKey)
- 生产者产生消息的地方需要指定
RoutingKey
,发送给 对应的 队列
通过DirectRabbitMQConfig配置类 创建交换机Direct、绑定队列、设置RoutingKey
DirectRabbitMQConfig配置类
package henu.soft.xiaosi.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;
@Configuration
public class DirectRabbitMQConfig {
// 1. 声明注册direct模式的交换机
@Bean
public DirectExchange directExchange(){
return new DirectExchange("direct_order_exchange",true,false);
}
// 2. 声明队列 sms.direct.queue 、email.direct.queue 、message.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 messageQueue(){
return new Queue("message.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 messageBinding(){
return BindingBuilder.bind(messageQueue()).to(directExchange()).with("message");
}
}
DirectOrderService生产类
package henu.soft.xiaosi.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;
@Configuration
public class DirectRabbitMQConfig {
// 1. 声明注册direct模式的交换机
@Bean
public DirectExchange directExchange(){
return new DirectExchange("direct_order_exchange",true,false);
}
// 2. 声明队列 sms.direct.queue 、email.direct.queue 、message.direct.queue
@Bean
public Queue smsDirectQueue(){
return new Queue("sms.direct.queue",true);
}
@Bean
public Queue emailDirectQueue(){
return new Queue("email.direct.queue",true);
}
@Bean
public Queue messageDirectQueue(){
return new Queue("message.direct.queue",true);
}
// 3. 完成绑定关系
@Bean
public Binding smsDirectBinding(){
return BindingBuilder.bind(smsDirectQueue()).to(directExchange()).with("sms");
}
@Bean
public Binding emailDirectBinding(){
return BindingBuilder.bind(emailDirectQueue()).to(directExchange()).with("email");
}
@Bean
public Binding messageDirectBinding(){
return BindingBuilder.bind(messageDirectQueue()).to(directExchange()).with("message");
}
}
4.路由模式-配置代码consumer
consumer对应业务修改为 对应的队列即可
package henu.sofi.xiaosi.springbootorderconsumer.service;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
@RabbitListener(queues = {"email.direct.queue"})
public class EmailService {
@RabbitHandler
public void receiveEmail(String id){
System.out.println("email direct 消费了订单信息是:--》" + id);
}
}
测试
@Test
void testDirect(){
// 模拟生产者,email为指定的RoutingKey
directOrderService.makeOrder("1","1",6,"email");
// 输出 订单生成成功c5ff0e9d-f5e3-4b19-8594-cabd40fec108
}
5.主题模式-配置代码producer
注意
- 前面两种 获取交换机、绑定队列都是在 配置类完成
- topic模式可以 通过在 consumer 的 注解 完成
队列、交换机
的绑定
TopicOrderService生产者类
package henu.soft.xiaosi.springbootorderrabbitmqproducer.service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class TopicOrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 模拟用户下单
* @param userId
* @param productId
* @param num
*/
public void makeOrder(String userId,String productId,int num, String routingKey){
// 1. 根据商品订单id查询库存是否充足
// 2. 保存订单
String orderId = UUID.randomUUID().toString();
System.out.println("订单生成成功" + orderId);
// 3. 通过消息队列完成消息的分发
// 除了使用配置类声明交换机、队列,还可以在consumer 通过注解的方式来绑定 交换机 和 队列
String exchangeName = "topic_order_exchange";
/**
* 参数
* 交换机
* 路由key、queue队列名称
* 消息内容
*/
// 关于交换机的生命、队列的声明、绑定需要写一个配置类
rabbitTemplate.convertAndSend(exchangeName,routingKey,orderId);
}
}
6.主题模式-配置代码(注解)consumer
EmailService消费者类
package henu.sofi.xiaosi.springbootorderconsumer.service;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Service;
// 注解方式绑定交换机、队列、routingKey
@Service
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "email.topic.queue",durable = "true",autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "#.sms.#"
))
public class EmailService {
@RabbitHandler
public void receiveEmail(String id){
System.out.println("email topic 消费了订单信息是:--》" + id);
}
}
测试