一套代码,两种部署:RuoYi Office 如何让你从单体无缝切换到微服务
🌐 官网:ruoyioffice.com | 📦 源码1:gitee.com/pansic-yuqi… |📦 源码2:gitee.com/yqzy1688/ru… |📦 源码3:github.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 微服务技术架构:从前端 Vue/UniApp → Nginx 接入 → Spring Cloud Gateway 网关 → 微服务集群 → MySQL/Redis/OSS/ES 存储,配合 Nacos、RocketMQ、Sentinel、Seata、SkyWalking 等分布式基础设施
从架构图中可以看到,整个系统分为 7 个层次:
但真正让 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 | 模块 JAR | yudao-server JAR |
|---|---|---|---|
-Pboot | true | 普通 JAR(仅包含自身 class) | Fat JAR(包含所有模块) |
-Pcloud | false | Fat 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 二级模块分离
每个业务模块都拆分为 api 和 server 两个子模块:
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 | 核心能力 | 封装对象 |
|---|---|---|---|
| Web | starter-web | 统一返回格式、全局异常处理、XSS 防护、Swagger 文档 | Spring MVC |
| 安全 | starter-security | JWT 认证、权限校验、多端登录 | Spring Security + OAuth 2.0 |
| 数据库 | starter-mybatis | 通用 CRUD 封装、分页插件、多数据源、国产数据库兼容 | MyBatis Plus 3.5 |
| 缓存 | starter-redis | Redis 操作封装、分布式锁 | Redisson 3.52 |
| RPC | starter-rpc | Feign 声明式 HTTP、负载均衡 | Spring Cloud OpenFeign |
| 消息 | starter-mq | 多消息中间件适配 | RocketMQ / Kafka / RabbitMQ |
| 任务 | starter-job | 分布式定时任务 | XXL-Job |
| 监控 | starter-monitor | 应用监控、链路追踪 | SkyWalking + Spring Boot Admin |
| 保障 | starter-protection | 限流、熔断、降级、分布式锁 | Sentinel + Redisson |
| WebSocket | starter-websocket | 实时消息推送、多端同步 | Spring WebSocket |
| Excel | starter-excel | Excel 导入导出 | FastExcel |
| 测试 | starter-test | 单元测试基础设施 | JUnit 5 + Mockito |
| 多租户 | starter-biz-tenant | SaaS 多租户数据隔离 | MyBatis 插件 |
| 数据权限 | starter-biz-data-permission | 行级数据权限控制 | MyBatis 拦截器 |
| IP 解析 | starter-biz-ip | IP → 地理位置映射 | ip2region |
| 环境 | starter-env | 开发环境标识、灰度标记 | Spring Cloud |
5.2 Starter 的分类哲学
这些 Starter 分为两大类:
框架类组件(技术通用,与业务无关):
starter-web、starter-mybatis、starter-redis、starter-security等- 特点:封装底层技术细节,提供开箱即用的配置
业务类组件(与具体业务相关,Maven 名包含 biz):
starter-biz-tenant、starter-biz-data-permission、starter-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 Boot | 3.5 | Java 生态事实标准,社区最活跃 |
| 微服务 | Spring Cloud | 2025.0 | 与 Spring Boot 3.5 完美匹配 |
| 微服务套件 | Spring Cloud Alibaba | 2023.0.3 | 阿里巴巴微服务全家桶,国内生态最成熟 |
| 网关 | Spring Cloud Gateway | — | 基于 Netty 的高性能网关 |
| 注册配置 | Nacos | 2.x | 注册中心 + 配置中心二合一 |
| 流程引擎 | Flowable | 7.2 | 最活跃的 BPMN 2.0 开源引擎 |
| ORM | MyBatis Plus | 3.5.15 | MyBatis 增强,CRUD 效率提升 300% |
| 缓存 | Redis + Redisson | 3.52 | 高性能缓存 + 分布式锁 |
| 消息队列 | RocketMQ | 2.3 | 阿里开源,金融级可靠性 |
| 链路追踪 | SkyWalking | 9.5 | APM 领域最流行的开源方案 |
| 分布式事务 | Seata | — | 阿里开源,AT 模式对业务无侵入 |
| 定时任务 | XXL-Job | 2.4 | 国内最流行的分布式任务调度 |
| 服务保障 | Sentinel | — | 阿里开源限流熔断框架 |
| API 文档 | Knife4j + SpringDoc | 4.5 / 2.8 | OpenAPI 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 | 功能 | 实现亮点 |
|---|---|---|
TokenAuthenticationFilter | JWT 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 / yarn | pnpm 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 构建配置
这个架构的核心价值:
- 组件复用:
packages/下的基础包被所有应用共享,一处修改全局生效 - UI 可切换:客户喜欢 Ant Design 就用 web-antd,喜欢 Element 就用 web-ele
- 独立构建:每个 app 独立打包部署,互不影响
- 统一规范:ESLint、TypeScript、Vite 配置集中管理
8.3 前端核心技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| Vue 3 | 3.5+ | 渐进式响应式框架 |
| TypeScript | 5.8 | 全量类型安全 |
| Vite | 6.3 | 极速构建(冷启动 < 1 秒) |
| Ant Design Vue | 4.x | 企业级 UI 组件库(主力) |
| Pinia | 2.x | Vue 3 推荐的状态管理 |
| Vue Router | 4.x | 路由管理 |
| Tailwind CSS | 3.x | 原子化 CSS |
| bpmn-js | — | BPMN 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 Native | Android + iOS | React | 主打 App |
| Flutter | Android + iOS + Web | Dart | 主打 App |
| UniApp | H5 + 小程序 + App + 鸿蒙 | Vue 3 | 企业级全端覆盖 |
选择 UniApp 的核心理由:
- 一套代码,全端覆盖——H5、微信小程序、支付宝小程序、App(Android + iOS)、鸿蒙,一次编写全平台发布
- Vue 3 技术栈统一——前端团队只需掌握 Vue 3,PC 端和移动端技术栈完全一致,人才复用
- 企业应用场景完美匹配——员工用小程序审批、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 内置了强大的代码生成器,支持从数据库表结构一键生成:
| 生成目标 | 包含内容 |
|---|---|
| 后端 Java | Controller、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 统一入口