RabbitMQ学习篇5_RabbitMQ整合SpringBoot 下单业务场景小练习(订阅发布模式 + 配置类、路由模式 + 配置类、主题模式+注解配置举栗)

本文详细介绍RabbitMQ中Fanout、Direct与Topic三种消息模式的实现过程,包括环境搭建、生产者与消费者的代码配置,并给出测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录
  • 环境配置
    • pom
    • yml
  • 下单业务场景
    1. 订阅发布-配置代码producer
    2. 通过 RabbitMQConfig配置类 创建交换机Fanout、绑定队列
    3. 订阅发布-配置代码consumer
    4. 路由模式-配置代码producer
    5. 通过DirectRabbitMQConfig配置类 创建交换机Direct、绑定队列、设置RoutingKey
    6. 路由模式-配置代码consumer
    7. 主题模式-配置代码producer
    8. 主题模式-配置代码(注解)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);
    }
}

测试

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scl、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值