一套代码,两种部署:RuoYi Office 如何让你从单体无缝切换到微服务

10 阅读20分钟

一套代码,两种部署:RuoYi Office 如何让你从单体无缝切换到微服务

🌐 官网ruoyioffice.com | 📦 源码1gitee.com/pansic-yuqi… |📦 源码2gitee.com/yqzy1688/ru… |📦 源码3github.com/yuqing2026/… | 💬 微信:17156169080(备注「RuoYi Office」)

中小企业信息化的终极答案——不是买更多软件,而是用一个平台覆盖所有业务。RuoYi Office 将 OA、BPM、HRM、CRM、ERP、AI 等 14 大模块整合到一个平台,让企业管理像使用一款 App 一样简单。

摘要:许多技术团队在项目初期都面临「单体还是微服务」的灵魂拷问。选单体怕将来扛不住,选微服务又怕早期过度设计。RuoYi Office 通过精巧的 Maven Profile + 模块化分层架构,实现了一套代码同时支持单体和微服务两种部署模式——项目初期用单体快速跑起来,业务增长后一键切换微服务,中间不改一行业务代码。本文将深度拆解这套架构背后的设计思想和工程实现。


一、你是否也踩过这些架构的坑?

在与数百位开发者的交流中,我们发现以下场景几乎每天都在上演:

😩 场景一:创业公司的「早期焦虑」

团队 3 个人,刚拿到天使轮,CTO 说「我们直接上微服务,方便将来扩展」。

结果:3 个人维护 Nacos + Gateway + 10 个微服务 + Docker + K8s,开发速度还不如隔壁用 PHP 的竞对,项目 6 个月后黄了。

😩 场景二:传统企业的「升级困境」

一个 Spring Boot 单体系统跑了 3 年,用户从 500 涨到 5000,系统越来越慢。

架构师提议「拆微服务」,结果发现代码高度耦合,模块之间互相 import,拆了 8 个月还没拆完,业务需求全部堵塞。

😩 场景三:外包团队的「选型纠结」

客户 A 说「我们就 50 人的公司,部署简单点」;客户 B 说「我们 2000 人,必须微服务」。

如果代码不一样,就要维护两套代码分支,Bug 修两遍,功能开发两遍。

这三个场景的本质问题是同一个:单体和微服务的架构选择,不应该是一道「二选一」的单选题。

RuoYi Office 的回答是——为什么不能两个都要?


二、架构总览:一套代码的「双面人生」

RuoYi Office 基于 Spring Boot 3.5 + Spring Cloud Alibaba 2023 + Vue 3.5 构建,在一套代码中天然支持两种部署形态:

2.1 两种部署模式对比

维度🟢 单体模式(Boot)🔵 微服务模式(Cloud)
启动方式一个 YudaoServerApplication 启动全部模块每个模块独立启动自己的 XxxServerApplication
进程数1 个 JVM 进程N 个 JVM 进程(按模块拆分)
模块间通信方法直调(同 JVM,零网络开销)OpenFeign HTTP 调用(跨进程)
注册中心❌ 不需要(Nacos 禁用)✅ Nacos 服务注册与发现
配置中心application-local.yaml 本地配置Nacos Config 统一配置
API 网关❌ 不需要(直连后端)✅ Spring Cloud Gateway 路由转发
数据库所有模块共享 1 个数据库实例每个模块可独立数据库(可选)
适用规模10~200 人企业 / 开发联调 / 快速交付200+ 人企业 / 高并发 / 弹性伸缩
切换成本一个 Maven 命令,零代码改动

2.2 微服务全景架构

下图是 RuoYi Office 微服务模式下的完整技术架构:

RuoYi Office 微服务技术架构全景图:涵盖前端服务、接入层、网关服务、微服务集群、存储层、分布式事务、定时任务、消息队列、配置注册中心、服务保障、运维工具和监控工具

▲ RuoYi Office 微服务技术架构:从前端 Vue/UniApp → Nginx 接入 → Spring Cloud Gateway 网关 → 微服务集群 → MySQL/Redis/OSS/ES 存储,配合 Nacos、RocketMQ、Sentinel、Seata、SkyWalking 等分布式基础设施

从架构图中可以看到,整个系统分为 7 个层次image.png 但真正让 RuoYi Office 与众不同的是——上面这张微服务架构图中的所有能力,在单体模式下一样具备(除了跨进程通信的部分),而且切换只需要一个 Maven 命令。

接下来,我们从源码级别拆解这套「双模架构」是如何实现的。


三、Maven Profile 双模切换机制:一键变身的秘密

3.1 根 pom.xml 的 Profile 定义

RuoYi Office 在项目根 pom.xml 中定义了两个 Maven Profile:

<!-- ruoyi-office/pom.xml -->
<profiles>
    <!-- boot 单体运行环境 -->
    <profile>
        <id>boot</id>
        <properties>
            <profile.name>boot</profile.name>
            <skip.repackage>true</skip.repackage>
        </properties>
    </profile>

    <!-- cloud 微服务运行环境(默认) -->
    <profile>
        <id>cloud</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <profile.name>cloud</profile.name>
            <skip.repackage>false</skip.repackage>
        </properties>
    </profile>
</profiles>

核心就在 skip.repackage 这个属性上,它控制了每个模块是否打出可独立运行的 Fat JAR。

3.2 模块的打包策略

每个业务模块(如 yudao-module-oa-server)的 pom.xml 中都有这样的配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!-- 单体模式下跳过 repackage,由 yudao-server 统一打包 -->
                <skip>${skip.repackage}</skip>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

yudao-server(单体入口)的打包配置则不使用 skip.repackage,始终执行 repackage:

<!-- yudao-server/pom.xml -->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <!-- 注意:yudao-server 始终需要 repackage,不使用 skip.repackage -->
</plugin>

3.3 双模切换的实际效果

# 🟢 单体模式打包:所有模块编译为普通 JAR → yudao-server 统一打包为 Fat JAR
mvn clean package -Pboot

# 🔵 微服务模式打包:每个模块各自打包为独立可运行的 Fat JAR
mvn clean package -Pcloud   # 或直接 mvn clean package(默认)
打包模式skip.repackage模块 JARyudao-server JAR
-Pboottrue普通 JAR(仅包含自身 class)Fat JAR(包含所有模块)
-PcloudfalseFat JAR(可独立运行)Fat JAR(作为默认单体入口备用)

3.4 单体模式的启动入口

yudao-server 是单体模式的统一入口,它做了三件关键事情:

第一,引入所有业务模块的依赖

<!-- yudao-server/pom.xml -->
<dependencies>
    <dependency>
        <groupId>cn.iocoder.cloud</groupId>
        <artifactId>yudao-module-system-server</artifactId>
    </dependency>
    <dependency>
        <groupId>cn.iocoder.cloud</groupId>
        <artifactId>yudao-module-infra-server</artifactId>
    </dependency>
    <dependency>
        <groupId>cn.iocoder.cloud</groupId>
        <artifactId>yudao-module-bpm-server</artifactId>
    </dependency>
    <dependency>
        <groupId>cn.iocoder.cloud</groupId>
        <artifactId>yudao-module-oa-server</artifactId>
    </dependency>
    <dependency>
        <groupId>cn.iocoder.cloud</groupId>
        <artifactId>yudao-module-hrm-server</artifactId>
    </dependency>
    <!-- 更多模块按需引入,注释即可不加载 -->
</dependencies>

注意:不需要的模块只需在 pom.xml 中注释掉依赖即可实现可插拔部署——只加载你需要的模块,减少资源消耗。

第二,扫描所有模块的包路径

@SpringBootApplication(scanBasePackages = {
    "${yudao.info.base-package}.server",
    "${yudao.info.base-package}.module"
})
public class YudaoServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(YudaoServerApplication.class, args);
    }
}

通过 ${yudao.info.base-package}.module 这个配置化扫描路径,所有模块的 Controller、Service、DAO 在同一个 Spring 容器中自动注册。

第三,禁用微服务组件

# yudao-server/application.yaml
spring:
  cloud:
    nacos:
      discovery:
        enabled: false  # 禁用 Nacos 注册发现
      config:
        enabled: false  # 禁用 Nacos 配置中心

同时在 pom.xml 中排除 OpenFeign:

<dependency>
    <groupId>cn.iocoder.cloud</groupId>
    <artifactId>yudao-spring-boot-starter-rpc</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </exclusion>
    </exclusions>
</dependency>

这样,在单体模式下,模块之间的 API 调用退化为同 JVM 内的本地方法调用——零网络开销,零序列化开销。

3.5 微服务模式的启动入口

每个模块都有自己独立的 Application 类和完整配置:

// yudao-module-oa-server
@SpringBootApplication
public class OaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(OaServerApplication.class, args);
    }
}
# yudao-module-oa-server/application.yaml
spring:
  application:
    name: oa-server
  config:
    import:
      - optional:classpath:application-${spring.profiles.active}.yaml
      - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml

server:
  port: 48101  # 每个服务独立端口

每个服务注册到 Nacos,由 Spring Cloud Gateway 统一路由。

3.6 为什么这个设计如此精妙?

传统方案:
  单体项目 (代码库 A) ──→ 要改微服务?重写! ──→ 微服务项目 (代码库 B)
                                   ↑ 6~12 个月

RuoYi Office 方案:
  一套代码 ─┬─ mvn -Pboot  ──→ 单体 JAR(适合初期 / 小规模)
            └─ mvn -Pcloud ──→ N 个微服务 JAR(适合增长期 / 大规模)
                                   ↑ 1 个命令,0 行代码改动

这意味着:

  • 初创团队可以先用单体快速上线,跑通业务
  • 业务增长后,只需切换打包命令 + 部署 Nacos/Gateway,即可升级为微服务
  • 外包团队用同一套代码库交付不同规模的客户
  • 开发联调用单体模式(启动快、调试方便),生产环境用微服务

四、模块化分层设计:不是拆代码,而是从设计上解耦

「能一键切换」只是表象,背后的核心是模块从第一天就按微服务的标准来设计,但不强制你用微服务来部署

4.1 项目目录全景

ruoyi-office/
├── pom.xml                          # 根 POM:定义 boot/cloud Profile
├── yudao-dependencies/              # BOM 统一依赖版本管理
├── yudao-framework/                 # 🧱 技术框架层(20+ 个 Starter)
│   ├── yudao-common/                #   通用工具类、基础 DTO
│   ├── yudao-common-server/         #   服务端通用能力
│   ├── yudao-spring-boot-starter-web/         # Web 相关封装
│   ├── yudao-spring-boot-starter-security/    # 安全认证
│   ├── yudao-spring-boot-starter-mybatis/     # 数据库访问
│   ├── yudao-spring-boot-starter-redis/       # 缓存
│   ├── yudao-spring-boot-starter-rpc/         # RPC 通信
│   ├── yudao-spring-boot-starter-mq/          # 消息队列
│   ├── yudao-spring-boot-starter-job/         # 定时任务
│   ├── yudao-spring-boot-starter-monitor/     # 监控
│   ├── yudao-spring-boot-starter-protection/  # 限流熔断
│   ├── yudao-spring-boot-starter-websocket/   # WebSocket
│   ├── yudao-spring-boot-starter-excel/       # Excel 导入导出
│   ├── yudao-spring-boot-starter-biz-tenant/  # 多租户
│   ├── yudao-spring-boot-starter-biz-data-permission/  # 数据权限
│   └── yudao-spring-boot-starter-biz-ip/      # IP 地域解析
│
├── yudao-gateway/                   # 🚪 API 网关(仅微服务模式使用)
├── yudao-server/                    # 📦 单体入口(仅单体模式使用)
│
├── yudao-module-system/             # 🔐 系统底座:用户、角色、权限、字典
│   ├── yudao-module-system-api/     #   对外暴露的 API 契约
│   └── yudao-module-system-server/  #   具体实现
├── yudao-module-infra/              # ⚙️ 基础设施:文件、配置、代码生成、日志
│   ├── yudao-module-infra-api/
│   └── yudao-module-infra-server/
│
├── yudao-module-bpm/                # ⚡ 流程中心(Flowable 7)
├── yudao-module-oa/                 # 🏢 OA 协同办公
├── yudao-module-hrm/                # 👥 人力资源
├── yudao-module-crm/                # 🤝 客户关系
├── yudao-module-erp/                # 📦 进销存
├── yudao-module-ai/                 # 🤖 AI 大模型
├── yudao-module-mall/               # 🛒 商城
├── yudao-module-pay/                # 💰 支付
├── yudao-module-member/             # 👤 会员
├── yudao-module-report/             # 📊 报表
├── yudao-module-mp/                 # 📱 公众号
├── yudao-module-iot/                # 🔗 物联网
├── yudao-module-asset/              # 🏷️ 资产管理
└── yudao-module-wms/                # 🏭 仓库管理

4.2 核心分层:system + infra 统一底座

这是 RuoYi Office 架构中最值得学习的设计之一。所有业务模块都共享两个公共底座:

┌──────────────────────────────────────────────────────┐
│                  业务模块层                            │
│  OA · BPM · HRM · CRM · ERP · AI · MALL · ...       │
│  每个模块只关注自己的业务逻辑                           │
├──────────────────────────────────────────────────────┤
│                 system 底座                           │
│  用户管理 · 角色权限 · 部门岗位 · 数据字典              │
│  OAuth 2.0 认证 · 社交登录 · 短信通知 · 邮件服务        │
├──────────────────────────────────────────────────────┤
│                 infra 底座                            │
│  文件存储 · 代码生成 · 操作日志 · 数据源管理             │
│  API 日志 · 配置管理 · WebSocket · 定时任务             │
├──────────────────────────────────────────────────────┤
│               yudao-framework 技术组件                │
│  Web · Security · MyBatis · Redis · RPC · MQ · ...   │
└──────────────────────────────────────────────────────┘

为什么要这样分?

  • system 底座封装了所有与「人」相关的基础能力——谁在用系统?他有什么权限?属于哪个部门?
  • infra 底座封装了所有与「基础设施」相关的能力——文件往哪存?日志怎么记?代码怎么生成?
  • 业务模块只需要关注自己的领域逻辑,通过 api 层调用底座服务,不需要重复造轮子

4.3 api/server 二级模块分离

每个业务模块都拆分为 apiserver 两个子模块:

yudao-module-oa/
├── pom.xml                      # 父 POM
├── yudao-module-oa-api/         # 📤 API 契约层(轻量级)
│   └── src/main/java/
│       └── cn.iocoder.yudao.module.oa/
│           ├── api/             # Feign 接口定义
│           │   └── OaFeignNotificationApi.java
│           └── enums/           # 枚举常量、API 路由常量
│               ├── ApiConstants.java
│               └── OaProcessVariableConstants.java
│
└── yudao-module-oa-server/      # 📥 业务实现层(重量级)
    ├── src/main/java/
    │   └── cn.iocoder.yudao.module.oa/
    │       ├── controller/      # REST API 层
    │       ├── service/         # 业务逻辑层
    │       ├── dal/             # 数据访问层(DO + Mapper)
    │       └── framework/       # 模块私有配置(安全、RPC 等)
    └── src/main/resources/
        ├── application.yaml     # 模块独立配置
        └── mapper/              # MyBatis XML

api 模块的设计哲学

特性说明
极致轻量仅包含接口定义、DTO、枚举,不包含任何实现代码
依赖极少只依赖 yudao-common,不引入 Spring Boot / MyBatis 等重量级框架
双重角色单体模式下是本地接口 → 直接调用实现类;微服务模式下是 Feign 接口 → HTTP 远程调用
模块解耦模块 A 只需依赖模块 B 的 api 包,不需要依赖 server 包

以 OA 模块调用 System 模块为例:

// 定义在 yudao-module-system-api 中的接口
public interface AdminUserApi {
    CommonResult<AdminUserRespDTO> getUser(@RequestParam("id") Long id);
}

// OA 模块中的使用方式——无论单体还是微服务,代码完全一致
@Service
public class SystemServiceImpl implements SystemService {

    @Resource
    private AdminUserApi adminUserApi;  // 注入 API 接口

    @Override
    public AdminUserRespDTO getUser(Long userId) {
        CommonResult<AdminUserRespDTO> result = adminUserApi.getUser(userId);
        return result.isSuccess() ? result.getData() : null;
    }
}

单体模式下,AdminUserApi 的实现类在同一个 Spring 容器中,直接本地调用;在微服务模式下,通过 @FeignClient 注解自动走 HTTP 远程调用——调用方的代码完全不需要改动

4.4 可插拔部署:按需加载

由于每个模块都是独立的 Maven Module,yudao-server 的 pom.xml 中通过注释即可控制模块的加载:

<!-- yudao-server/pom.xml -->

<!-- ✅ 核心模块(必须) -->
<dependency>
    <artifactId>yudao-module-system-server</artifactId>
</dependency>
<dependency>
    <artifactId>yudao-module-infra-server</artifactId>
</dependency>

<!-- ✅ 按需加载的模块 -->
<dependency>
    <artifactId>yudao-module-bpm-server</artifactId>
</dependency>
<dependency>
    <artifactId>yudao-module-oa-server</artifactId>
</dependency>

<!-- ❌ 暂不需要的模块(注释即可) -->
<!--
<dependency>
    <artifactId>yudao-module-mall-server</artifactId>
</dependency>
<dependency>
    <artifactId>yudao-module-crm-server</artifactId>
</dependency>
-->

这意味着:

  • 只做 OA 的客户?加载 system + infra + bpm + oa,4 个模块就够
  • 需要全功能?取消注释,加载全部 14 个模块
  • 某模块有性能瓶颈?只把它拆出去独立部署,其他继续单体

这才是真正的「渐进式微服务」——不是一刀切,而是按需演进。


五、yudao-framework:20+ 个 Spring Boot Starter 的技术底座

5.1 Starter 组件全景

yudao-framework 不是一个大而全的 JAR,而是拆分为 20+ 个独立的 Spring Boot Starter,每个 Starter 职责单一、可独立引入:

类别Starter核心能力封装对象
Webstarter-web统一返回格式、全局异常处理、XSS 防护、Swagger 文档Spring MVC
安全starter-securityJWT 认证、权限校验、多端登录Spring Security + OAuth 2.0
数据库starter-mybatis通用 CRUD 封装、分页插件、多数据源、国产数据库兼容MyBatis Plus 3.5
缓存starter-redisRedis 操作封装、分布式锁Redisson 3.52
RPCstarter-rpcFeign 声明式 HTTP、负载均衡Spring Cloud OpenFeign
消息starter-mq多消息中间件适配RocketMQ / Kafka / RabbitMQ
任务starter-job分布式定时任务XXL-Job
监控starter-monitor应用监控、链路追踪SkyWalking + Spring Boot Admin
保障starter-protection限流、熔断、降级、分布式锁Sentinel + Redisson
WebSocketstarter-websocket实时消息推送、多端同步Spring WebSocket
Excelstarter-excelExcel 导入导出FastExcel
测试starter-test单元测试基础设施JUnit 5 + Mockito
多租户starter-biz-tenantSaaS 多租户数据隔离MyBatis 插件
数据权限starter-biz-data-permission行级数据权限控制MyBatis 拦截器
IP 解析starter-biz-ipIP → 地理位置映射ip2region
环境starter-env开发环境标识、灰度标记Spring Cloud

5.2 Starter 的分类哲学

这些 Starter 分为两大类:

框架类组件(技术通用,与业务无关):

  • starter-webstarter-mybatisstarter-redisstarter-security
  • 特点:封装底层技术细节,提供开箱即用的配置

业务类组件(与具体业务相关,Maven 名包含 biz):

  • starter-biz-tenantstarter-biz-data-permissionstarter-biz-ip
  • 特点:封装业务通用逻辑,如多租户的 SQL 自动拼接

5.3 设计收益

❌ 传统做法:一个巨大的 common 包,所有项目都引入全部依赖
   → 依赖膨胀、启动慢、升级困难

✅ RuoYi Office 做法:20+ 个细粒度 Starter,按需引入
   → 模块只引入自己需要的能力,依赖清晰、启动快

例如,yudao-module-oa-server 的依赖声明,清晰表达了它需要哪些技术能力:

<!-- OA 模块需要的技术组件 -->
<dependency>
    <artifactId>yudao-spring-boot-starter-web</artifactId>          <!-- Web 能力 -->
</dependency>
<dependency>
    <artifactId>yudao-spring-boot-starter-security</artifactId>     <!-- 安全认证 -->
</dependency>
<dependency>
    <artifactId>yudao-spring-boot-starter-mybatis</artifactId>      <!-- 数据库访问 -->
</dependency>
<dependency>
    <artifactId>yudao-spring-boot-starter-redis</artifactId>        <!-- 缓存 -->
</dependency>
<dependency>
    <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>   <!-- 多租户 -->
</dependency>
<dependency>
    <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>  <!-- 数据权限 -->
</dependency>

六、技术选型详解:为什么选这些?

6.1 后端技术栈全景

层次技术版本选型理由
基础框架Spring Boot3.5Java 生态事实标准,社区最活跃
微服务Spring Cloud2025.0与 Spring Boot 3.5 完美匹配
微服务套件Spring Cloud Alibaba2023.0.3阿里巴巴微服务全家桶,国内生态最成熟
网关Spring Cloud Gateway基于 Netty 的高性能网关
注册配置Nacos2.x注册中心 + 配置中心二合一
流程引擎Flowable7.2最活跃的 BPMN 2.0 开源引擎
ORMMyBatis Plus3.5.15MyBatis 增强,CRUD 效率提升 300%
缓存Redis + Redisson3.52高性能缓存 + 分布式锁
消息队列RocketMQ2.3阿里开源,金融级可靠性
链路追踪SkyWalking9.5APM 领域最流行的开源方案
分布式事务Seata阿里开源,AT 模式对业务无侵入
定时任务XXL-Job2.4国内最流行的分布式任务调度
服务保障Sentinel阿里开源限流熔断框架
API 文档Knife4j + SpringDoc4.5 / 2.8OpenAPI 3.0 标准
数据库MySQL / PostgreSQL / 达梦 / 人大金仓多数据库兼容 + 国产化信创

6.2 为什么选 Spring Cloud Alibaba 而不是 Netflix?

维度Spring Cloud Netflix(已停维)Spring Cloud Alibaba
注册中心Eureka(停止更新)Nacos(持续迭代,兼任配置中心)
负载均衡Ribbon(停止更新)Spring Cloud LoadBalancer
限流熔断Hystrix(停止更新)Sentinel(阿里生产级验证)
分布式事务无内置方案Seata(AT/TCC/Saga 多模式)
消息驱动无内置方案RocketMQ(金融级可靠性)
配置中心Spring Cloud Config(原始)Nacos Config(UI 可视化管理)
国内社区萎缩极度活跃,阿里持续投入

答案很明显:在国内企业级应用场景下,Spring Cloud Alibaba 是经过双十一 + 海量企业生产验证的最佳选择

6.3 统一依赖版本管理

yudao-dependencies 模块作为全项目的 BOM(Bill of Materials),统一管理所有第三方依赖的版本号:

<!-- yudao-dependencies/pom.xml -->
<properties>
    <spring.boot.version>3.5.9</spring.boot.version>
    <spring.cloud.version>2025.0.0</spring.cloud.version>
    <spring.cloud.alibaba.version>2023.0.3.3</spring.cloud.alibaba.version>
    <flowable.version>7.2.0</flowable.version>
    <mybatis-plus.version>3.5.15</mybatis-plus.version>
    <redisson.version>3.52.0</redisson.version>
    <skywalking.version>9.5.0</skywalking.version>
    <!-- 70+ 个依赖版本集中管控 -->
</properties>

收益

  • 🔒 杜绝版本冲突——所有模块使用同一版本的 Jackson、Netty、Log4j 等
  • ⬆️ 安全升级一步到位——修改 BOM 一处,全项目生效
  • 📦 新模块零配置——引入依赖无需指定版本号

七、Spring Cloud Gateway 网关层设计

7.1 网关核心能力

在微服务模式下,Spring Cloud Gateway 是所有 API 请求的统一入口,承担了 5 项核心职责:

客户端请求 ──→ Gateway ──→ 后端微服务
                │
    ┌───────────┼───────────┐───────────┐───────────┐
    │           │           │           │           │
  路由转发    安全鉴权    访问日志    CORS跨域    灰度发布

7.2 关键 Filter 实现

Filter功能实现亮点
TokenAuthenticationFilterJWT Token 校验解析 Token → 注入用户信息到请求头 → 传递给下游服务
CorsFilter跨域处理全局 CORS 配置,前端无需额外处理
AccessLogFilter访问日志记录请求/响应全链路日志,方便排查问题
GrayReactiveLoadBalancerClientFilter灰度路由根据请求标记路由到灰度环境,支持金丝雀发布

7.3 灰度发布支持

// GrayLoadBalancer.java - 灰度路由负载均衡器
// 根据请求头中的环境标记(如 tag=gray),
// 将流量路由到对应灰度实例,
// 实现不停机的金丝雀发布

这意味着在微服务模式下,你可以:

  • 新版本只部署一个实例,导入 5% 的流量测试
  • 确认无问题后,逐步扩大流量比例
  • 出现问题时,一秒回退到稳定版本

八、前端架构:Vben Admin 5 企业级工程化方案

8.1 为什么选择 Vben Admin?

维度传统 Vue 后台模板Vben Admin 5
架构单体 SPA 项目Monorepo + Turborepo 工程化方案
UI 库绑定单一 UI 框架4 套 UI 同时支持(Ant Design / Element Plus / Naive / TDesign)
TypeScript可选 / 弱类型全量 TypeScript,严格类型检查
包管理npm / yarnpnpm Workspace,依赖管理更高效
主题简单换色CSS 变量 + Tailwind CSS 深度定制
代码复用复制粘贴workspace 共享包,组件/工具跨应用复用

8.2 Monorepo 多应用架构

ruoyi-office-vben/
├── packages/                        # 🧱 共享基础包
│   ├── @vben/access/                # 权限控制
│   ├── @vben/common-ui/             # 通用 UI 组件
│   ├── @vben/hooks/                 # 组合式函数
│   ├── @vben/layouts/               # 布局系统
│   ├── @vben/request/               # HTTP 请求封装
│   ├── @vben/stores/                # 状态管理
│   └── @vben/utils/                 # 工具函数
│
├── apps/                            # 📱 多应用实例
│   ├── web-antd/                    # Ant Design Vue 版本 ← RuoYi Office 主力
│   ├── web-ele/                     # Element Plus 版本
│   ├── web-naive/                   # Naive UI 版本
│   └── web-tdesign/                 # TDesign 版本
│
└── internal/                        # 🔧 内部工具
    ├── lint-configs/                # ESLint/Prettier 规则
    └── vite-config/                 # Vite 构建配置

这个架构的核心价值

  1. 组件复用packages/ 下的基础包被所有应用共享,一处修改全局生效
  2. UI 可切换:客户喜欢 Ant Design 就用 web-antd,喜欢 Element 就用 web-ele
  3. 独立构建:每个 app 独立打包部署,互不影响
  4. 统一规范:ESLint、TypeScript、Vite 配置集中管理

8.3 前端核心技术栈

技术版本用途
Vue 33.5+渐进式响应式框架
TypeScript5.8全量类型安全
Vite6.3极速构建(冷启动 < 1 秒)
Ant Design Vue4.x企业级 UI 组件库(主力)
Pinia2.xVue 3 推荐的状态管理
Vue Router4.x路由管理
Tailwind CSS3.x原子化 CSS
bpmn-jsBPMN 2.0 流程可视化设计器
TinyMCE富文本编辑器

8.4 与后端的协作约定

前后端的协作基于以下统一约定:

// 统一响应格式
interface CommonResult<T> {
  code: number    // 0 = 成功,非 0 = 错误
  data: T         // 业务数据
  msg: string     // 提示消息
}

// 统一分页格式
interface PageResult<T> {
  list: T[]       // 当前页数据
  total: number   // 总记录数
}

// API 模块化组织,与后端模块一一对应
// src/api/oa/car-info.ts → /admin-api/oa/car-info/*
// src/api/system/user.ts  → /admin-api/system/user/*

九、移动端架构:UniApp 跨端方案

9.1 为什么选择 UniApp?

在移动端框架的选型中,RuoYi Office 选择了 UniApp + Vue 3 方案:

方案跨端能力技术栈适合场景
原生开发❌ 各端独立Swift/Kotlin追求极致体验
React NativeAndroid + iOSReact主打 App
FlutterAndroid + iOS + WebDart主打 App
UniAppH5 + 小程序 + App + 鸿蒙Vue 3企业级全端覆盖

选择 UniApp 的核心理由

  1. 一套代码,全端覆盖——H5、微信小程序、支付宝小程序、App(Android + iOS)、鸿蒙,一次编写全平台发布
  2. Vue 3 技术栈统一——前端团队只需掌握 Vue 3,PC 端和移动端技术栈完全一致,人才复用
  3. 企业应用场景完美匹配——员工用小程序审批、App 移动办公、H5 内嵌到企业微信/钉钉

9.2 移动端技术架构

ruoyi-office-uniapp/
├── src/
│   ├── api/                  # API 接口(与 PC 端共享后端 API)
│   │   ├── bpm/              # BPM 流程相关接口
│   │   ├── system/           # 系统管理接口
│   │   └── infra/            # 基础设施接口
│   ├── pages/                # 主包页面
│   │   ├── index/            # 首页(工作台)
│   │   ├── bpm/              # 审批相关
│   │   ├── contact/          # 通讯录
│   │   ├── message/          # 消息中心
│   │   └── user/             # 个人中心
│   ├── pages-bpm/            # BPM 分包(流程详情、OA 审批等)
│   ├── pages-core/           # 核心分包(登录、用户资料等)
│   ├── pages-system/         # 系统管理分包
│   ├── pages-infra/          # 基础设施分包
│   ├── store/                # Pinia 状态管理
│   ├── http/                 # HTTP 封装(Token 拦截器、统一错误处理)
│   └── hooks/                # 组合式函数(权限、字典、上传等)

9.3 PC 与移动端的后端统一

一套后端 API,同时服务 PC 和移动端——这是 RuoYi Office 的一个重要设计原则:

┌─────────────────┐   ┌─────────────────┐
│  PC 端(Vue 3)  │   │  移动端(UniApp) │
│  Vben Admin      │   │  H5 / 小程序 / App│
└────────┬────────┘   └────────┬────────┘
         │                     │
         │  /admin-api/*       │  /admin-api/*
         │  /app-api/*         │  /app-api/*
         │                     │
┌────────▼─────────────────────▼────────┐
│          统一后端 API 层               │
│   相同的 Controller / Service / DAO    │
│   相同的鉴权 / 数据权限 / 多租户       │
└───────────────────────────────────────┘

移动端不需要独立的后端服务,而是复用 PC 端的全部 API——这意味着:

  • 新增一个 API,PC 和移动端同时可用
  • 权限控制全局一致,不会出现移动端越权
  • 后端团队无需为移动端额外开发接口

十、工程化细节:让架构真正落地

10.1 统一编码规范

后端 Controller 层规范

@Tag(name = "管理后台 - 车辆信息")              // OpenAPI 3.0 文档
@RestController
@RequestMapping("/oa/car-info")
@Validated                                      // 参数校验
public class OaCarInfoController {

    @Resource
    private OaCarInfoService carInfoService;

    @PostMapping("/create")
    @Operation(summary = "创建车辆信息")          // 接口文档
    @PreAuthorize("@ss.hasPermission('oa:car-info:create')")  // 权限控制
    public CommonResult<Long> createCarInfo(
            @Valid @RequestBody OaCarInfoSaveReqVO createReqVO) {  // 入参校验
        return success(carInfoService.createCarInfo(createReqVO));
    }
}

每个接口天然具备:

  • 📖 Swagger 文档注解
  • 🔐 Spring Security 权限控制
  • ✅ JSR 380 参数校验
  • 📦 统一返回 CommonResult<T> 格式

10.2 代码生成器:一键生成前后端代码

yudao-module-infra 内置了强大的代码生成器,支持从数据库表结构一键生成:

生成目标包含内容
后端 JavaController、VO(增删改查)、Service、ServiceImpl、Mapper、DO
前端 Vue 3(Vben 5)API 定义、列表页、表单弹窗、详情页
前端 UniApp移动端列表页、详情页、组件
SQL建表 DDL、菜单权限数据

支持的前端模板多达 6 种

codegen/
├── vue3_vben5_antd/      # Vben 5 + Ant Design Vue(推荐)
├── vue3_vben5_ele/       # Vben 5 + Element Plus
├── vue3_vben/            # Vben 2(旧版兼容)
├── vue3/                 # 原始 Vue 3 + Element Plus
├── vue/                  # Vue 2(旧版兼容)
└── vue3_admin_uniapp/    # UniApp 移动端

10.3 国产化兼容

维度支持情况
数据库MySQL · PostgreSQL · 达梦(DM) · 人大金仓(KingBase) · OpenGauss
操作系统麒麟(Kylin) · 统信(UOS) · 中标麒麟
中间件东方通(TongWeb)
CPU 架构x86 · ARM(鲲鹏/飞腾) · MIPS(龙芯)

MyBatis Plus 的 DbType 枚举 + 自定义方言适配,实现了同一套 Java 代码无缝兼容多种数据库。yudao-dependencies 中已预置了达梦(DmJdbcDriver18)和人大金仓(kingbase8)的 JDBC 驱动依赖。


十一、真实演进路径:从 1 人到 1000 人的架构之旅

阶段一:项目启动期(1~5 人团队)

# 单体模式启动,5 分钟跑起来
mvn clean package -Pboot
java -jar yudao-server.jar
  • 部署 1 台服务器(2 核 4G 即可)
  • 只加载需要的模块(system + infra + bpm + oa)
  • 数据库 1 个 MySQL 实例
  • 不需要 Nacos、Gateway、Redis 集群
  • 专注业务开发,不被基础设施拖慢

阶段二:业务增长期(5~20 人团队)

# 仍然单体模式,但加载更多模块
# 在 yudao-server/pom.xml 中取消注释 CRM、ERP 等模块
mvn clean package -Pboot
  • 部署 2 台服务器(Nginx 负载均衡)
  • Redis 独立部署用于缓存和分布式锁
  • 数据库主从分离
  • 依然是单体,但开始为微服务做准备

阶段三:规模扩展期(20~100 人团队)

# 切换微服务模式,将压力大的模块独立部署
mvn clean package -Pcloud
  • 部署 Nacos 作为注册配置中心
  • Spring Cloud Gateway 统一入口