基于 Spring Boot + RabbitMQ 实现应用通信

一、应用通信架构设计

1.1 需求场景

用户在订单系统 完成下单后,订单系统无需直接调用物流系统接口,而是通过 RabbitMQ 发送"下单成功"消息;物流系统监听 RabbitMQ 队列,接收消息后触发发货流程,实现"订单-物流"两个独立应用的异步通信。

1.2 架构图

  • 角色划分:订单系统作为生产者,负责发送消息;物流系统作为消费者,负责接收并处理消息;
  • 核心组件 :使用 RabbitMQ 的简单队列(order.create)实现消息传递,队列持久化确保消息不丢失;
  • 解耦优势:订单系统与物流系统无需感知对方地址,只需通过 RabbitMQ 交互,减少系统耦合。

二、前置准备:环境与依赖

2.1 环境要求

  • JDK 8+(文档中推荐版本,兼容性稳定);
  • Spring Boot 2.7.x 或 3.x(本文以 2.7.10 为例);
  • RabbitMQ 服务(文档中使用云服务器部署,地址 110.41.51.65:15673,虚拟主机 bite,用户 study/study)。

2.2 依赖引入

两个应用(订单系统、物流系统)均需引入 Spring Boot RabbitMQ 依赖和 Web 依赖(订单系统需提供下单接口),pom.xml 配置如下:

xml 复制代码
<!-- Spring Boot RabbitMQ 整合依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- Web 依赖:订单系统用于提供下单接口 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 测试依赖(可选) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

三、步骤1:搭建订单系统(生产者)

订单系统的核心功能是"处理下单逻辑"并"发送消息到 RabbitMQ",需完成配置、队列声明、接口编写三个核心步骤。

3.1 配置 RabbitMQ 连接

src/main/resources/application.yml 中配置 RabbitMQ 连接信息(与文档中一致):

yaml 复制代码
server:
  port: 8080  # 订单系统端口(避免与物流系统冲突)

spring:
  rabbitmq:
    # 连接地址:amqp://用户名:密码@IP:端口/虚拟主机
    addresses: amqp://study:study@110.41.51.65:5672/bite
    # 可选:单独配置参数(与addresses二选一)
    # host: 110.41.51.65
    # port: 5672
    # username: study
    # password: study
    # virtual-host: bite

3.2 声明通信队列

通过 @Configuration 类声明持久化队列 order.create(确保 RabbitMQ 重启后队列不丢失):

java 复制代码
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    // 声明订单-物流通信队列(durable=true:持久化)
    @Bean("orderQueue")
    public Queue orderQueue() {
        return QueueBuilder.durable("order.create").build();
    }
}

3.3 编写下单接口与消息发送逻辑

创建 OrderController,提供下单接口,下单成功后通过 RabbitTemplate 发送消息到 order.create 队列:

java 复制代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;

@RestController
@RequestMapping("/order")
public class OrderController {
    // 注入 Spring 自动创建的 RabbitTemplate(消息发送模板)
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 下单接口:模拟用户下单,发送消息到物流系统
     */
    @RequestMapping("/createOrder")
    public String createOrder() {
        // 1. 模拟下单逻辑(实际场景需包含参数校验、数据库操作等)
        String orderId = UUID.randomUUID().toString(); // 生成唯一订单ID
        String orderMsg = "下单成功,订单ID:" + orderId;
        System.out.println("订单系统:" + orderMsg);

        // 2. 发送消息到 RabbitMQ 的 order.create 队列
        // 参数1:交换机(默认交换机,空字符串)
        // 参数2:路由键(队列名,与声明的队列一致)
        // 参数3:消息内容
        rabbitTemplate.convertAndSend("", "order.create", orderMsg);

        return "下单成功!订单ID:" + orderId;
    }
}

四、步骤2:搭建物流系统(消费者)

物流系统的核心功能是"监听 RabbitMQ 队列",接收订单系统发送的消息并触发发货逻辑,只需完成配置和监听逻辑编写。

4.1 配置 RabbitMQ 连接

物流系统需与订单系统连接到同一 RabbitMQ 服务,application.yml 配置如下(端口设为 9090,避免与订单系统冲突):

yaml 复制代码
server:
  port: 9090  # 物流系统端口(与订单系统不同)

spring:
  rabbitmq:
    # 与订单系统一致的 RabbitMQ 连接信息
    addresses: amqp://study:study@110.41.51.65:15673/bite

4.2 编写消息监听逻辑

通过 @RabbitListener 注解声明监听 order.create 队列,接收消息后模拟发货处理:

java 复制代码
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class OrderMessageListener {
    /**
     * 监听 order.create 队列,接收订单消息并处理发货
     * @param message 订单系统发送的消息内容
     */
    @RabbitListener(queues = "order.create") // 直接指定监听的队列名
    public void handleOrderMessage(String message) {
        // 模拟物流系统处理逻辑:接收消息、解析订单信息、调用发货接口等
        System.out.println("物流系统:" + message + ",开始安排发货...");
        // 实际场景需添加:订单信息解析、调用物流API、更新发货状态等代码
    }
}
  • @RabbitListener 是 Spring AMQP 核心注解,无需手动创建连接或通道,Spring 会自动管理监听逻辑;
  • 方法参数 String message 直接接收消息内容(Spring 自动完成消息反序列化),也可使用 Message 类型获取消息属性(如消息ID、路由键等)。

五、步骤3:运行验证应用通信

5.1 启动服务

  1. 先启动物流系统(确保消费者已监听队列,避免消息丢失);
  2. 再启动订单系统(生产者就绪,可发送消息)。

5.2 触发下单与消息发送

通过浏览器或 Postman 访问订单系统的下单接口:

  • 接口地址:http://127.0.0.1:8080/order/createOrder
  • 接口返回:下单成功!订单ID:xxx-xxx-xxx-xxx(xxx 为 UUID 生成的唯一ID)

5.3 观察日志验证通信结果

  1. 订单系统日志 :打印 订单系统:下单成功,订单ID:xxx-xxx-xxx-xxx,表示消息已发送;
  2. 物流系统日志 :打印 物流系统:下单成功,订单ID:xxx-xxx-xxx-xxx,开始安排发货...,表示消息已接收并处理;
  3. RabbitMQ 管理界面验证
    • 访问 RabbitMQ 管理界面(http://110.41.51.65:15672),切换到 bite 虚拟主机;
    • 点击 Queues 标签,找到 order.create 队列,Ready 列显示 0(消息已被消费),Consumers 列显示 1(物流系统已监听)。

六、进阶:发送对象类型消息(非字符串)

实际场景中,应用间常需传递复杂数据(如订单详情对象),需配置 JSON 序列化器,确保对象能在不同应用间正确传输。

6.1 配置 JSON 消息序列化器

在订单系统和物流系统中,均添加消息转换器配置(使用 Jackson2JsonMessageConverter):

java 复制代码
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQMessageConfig {
    // 配置 RabbitTemplate 的消息转换器(JSON 序列化)
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(new Jackson2JsonMessageConverter());
        return template;
    }

    // 配置消费者的消息转换器(确保能正确反序列化对象)
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        return factory;
    }
}

6.2 定义订单对象

在两个应用中创建相同的 OrderInfo 实体类(包路径需一致,确保反序列化成功):

java 复制代码
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

// Lombok 注解:自动生成 getter/setter、构造方法(需引入 lombok 依赖)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderInfo {
    private String orderId;    // 订单ID
    private String productName;// 商品名称
    private Long totalPrice;   // 订单总价
}

若未使用 Lombok,需手动编写 getter、setter 和构造方法。

6.3 修改消息发送与接收逻辑

订单系统(生产者):发送 OrderInfo 对象
java 复制代码
@RequestMapping("/createOrderWithObject")
public String createOrderWithObject() {
    // 1. 构建订单对象
    String orderId = UUID.randomUUID().toString();
    OrderInfo orderInfo = new OrderInfo(orderId, "手机", 5999L);
    System.out.println("订单系统:发送订单对象," + orderInfo);

    // 2. 发送对象消息(RabbitTemplate 自动序列化为 JSON)
    rabbitTemplate.convertAndSend("", "order.create", orderInfo);

    return "下单成功!订单详情:" + orderInfo;
}
物流系统(消费者):接收 OrderInfo 对象
java 复制代码
// 监听 order.create 队列,直接接收 OrderInfo 对象
@RabbitListener(queues = "order.create")
public void handleOrderObjectMessage(OrderInfo orderInfo) {
    System.out.println("物流系统:接收订单对象,开始发货...");
    System.out.println("订单ID:" + orderInfo.getOrderId());
    System.out.println("商品名称:" + orderInfo.getProductName());
    System.out.println("订单总价:" + orderInfo.getTotalPrice());
}

6.4 验证对象消息通信

访问订单系统接口 http://127.0.0.1:8080/order/createOrderWithObject,物流系统日志会打印订单对象的详细信息,表明对象消息已正确传输。

七、注意事项

  1. 端口冲突:两个应用需使用不同端口(如订单 8080、物流 9090),避免启动失败;
  2. 队列一致性 :生产者声明的队列名(order.create)需与消费者监听的队列名完全一致,否则消息无法路由;
  3. 消息可靠性
    • 队列需配置 durable=true(持久化),避免 RabbitMQ 重启后队列丢失;
    • 若需确保消息不丢失,可开启"发布确认模式"(参考文档中 Publisher Confirms 模式)和"消费者手动确认";
  4. 对象序列化 :跨应用传递对象时,需确保两个应用的实体类包路径、字段名、类型完全一致,并配置统一的序列化器(如 JSON);
  5. 虚拟主机隔离 :文档中使用 bite 虚拟主机,实际场景中不同业务线应使用独立虚拟主机,通过 virtual-host 配置实现资源隔离。
相关推荐
汤姆yu5 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
暮色妖娆丶6 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
biyezuopinvip7 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
JavaGuide7 小时前
一款悄然崛起的国产规则引擎,让业务编排效率提升 10 倍!
java·spring boot
figo10tf8 小时前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
zhangyi_viva8 小时前
Spring Boot(七):Swagger 接口文档
java·spring boot·后端
橙露8 小时前
Spring Boot 核心原理:自动配置机制与自定义 Starter 开发
java·数据库·spring boot
程序员敲代码吗8 小时前
Spring Boot与Tomcat整合的内部机制与优化
spring boot·后端·tomcat
NuageL8 小时前
原始Json字符串转化为Java对象列表/把中文键名变成英文键名
java·spring boot·json
jzheng86108 小时前
Spring Boot(快速上手)
java·spring boot·后端