导览 · 项目全景与技术架构
本文是 RuoYi-Vue-Pro(芋道快速开发平台)源码深度学习的开篇导读。它帮你建立全局认知:这个项目是什么、由什么组成、一次请求如何贯穿全栈、以及应该如何逐步深入。后续每一章都是对某一个模块的显微镜级拆解。
1. 项目背景与目标
RuoYi-Vue-Pro 是国内极具影响力的 Java 快速开发平台(由「芋道源码」维护,本仓库为 ruoyi-vue-pro,对应的云原生版是 yudao-cloud)。它有很鲜明的几个特征:
- 定位:以开发者为中心,主打”拿来即用、快速复刻业务系统”,个人与企业可 100% 免费使用(MIT 协议)。
- 技术底座:
master分支为 JDK 8 + Spring Boot 2.7.18(另有master-jdk17分支为 Spring Boot 3.2),采用 Spring Boot 多模块(Maven multi-module)架构。 - 覆盖广度:一个仓库内同时容纳了系统功能、基础设施、工作流(Flowable)、支付、商城、CRM、ERP、微信公众号、AI 大模型等十余条业务线。
- 代码规模:README 自述约 113,770 行 Java 代码、42,462 行注释;本仓库已启用(开启编译)的模块是
system(系统,387 个 Java 文件)与infra(基础设施,201 个 Java 文件),其余bpm/pay/mall/crm/erp/ai/mp/report等模块在根pom.xml中默认注释关闭,可按需开启(见 第十一章 搭建与复刻指南)。
需要特别说明的是:这套项目的价值不止于”能用”,更在于它的分层与约定。对于一个学习 Java 企业级工程的人来说,读懂它的通用基础层(yudao-framework)是怎么把错误码、统一返回、鉴权、多租户、数据权限这些”横切关注点”抽象成可复用 Starter 的,比读懂任何单一业务模块都有价值得多。这也是本学习文档的核心主线。
2. 核心概念速览
| 术语 | 含义 | 首次出现章节 |
|---|---|---|
CommonResult<T> |
全项目统一 API 返回包装:code + data + msg,成功 code = 0 |
第二章 错误码与统一返回 |
ErrorCode |
不可变的错误码对象(code + msg),全局码 [0,999]、业务码 [1_000_000_000, +∞) |
第二章 |
ServiceException |
业务异常,业务代码通过它中断流程并携带 readable 的提示文本 | 第二章 |
BaseDO |
所有数据库实体的公共父类:createTime/updateTime/creator/updater/deleted,由 MyBatis 自动填充 |
第五章 MyBatis 数据层 |
LoginUser |
登录用户模型,作为 Spring Security Authentication.getPrincipal() 的主体 |
第四章 安全与鉴权 |
TokenAuthenticationFilter |
每次请求从 Header/参数中取 Token,换得 LoginUser 注入 Security 上下文的过滤器 |
第四章 |
PermissionApi |
framework(security)与 module(system)之间面向接口的调用边界,屏蔽模块间依赖 | 第四章 / 第八章 |
OAuth2 AccessToken |
登录成功后签发的访问令牌,主存 Redis、备存 MySQL | 第七章 登录全流程 |
设计哲学可以用一句话概括:
「框架只管通用的横切能力,业务模块只关心自己的领域。」 跨模块协作一律走
xxxApi接口,通用能力一律下沉到yudao-framework下的独立 Spring Boot Starter。
3. 典型场景剖析
场景 A:一个管理后台用户「登录」并「访问受保护接口」
这是理解全工程的最短路径,完整逐行解读见 第七章 登录全流程。这里先看它在高层是怎么流动的:
sequenceDiagram
participant U as 前端 Vue
participant RT as TokenAuthenticationFilter
participant SC as Spring Security 上下文
participant C as AuthController
participant S as AdminAuthServiceImpl
participant T as OAuth2TokenServiceImpl
U->>RT: POST /admin-api/system/auth/login (username+password+captcha)
RT->>RT: 该 URL 带 @PermitAll,放行(无 Token 也进入 Controller)
RT->>C: 继续向下游
C->>S: authService.login(reqVO)
S->>S: validateCaptcha() 校验图形验证码
S->>S: authenticate() 校验账号/密码/状态,记录登录日志
S->>T: oauth2TokenService.createAccessToken(userId, ADMIN, defaultClient, scopes)
T->>T: 生成 refreshToken + accessToken(UUID),落库 MySQL + 写 Redis
T-->>S: 返回 OAuth2AccessTokenDO
S-->>C: AuthConvert 转成 AuthLoginRespVO(accessToken+refreshToken+expires)
C-->>U: CommonResult.success(loginRespVO)
Note over U: 前端保存 accessToken,之后每次请求带 Authorization: Bearer
U->>RT: GET /admin-api/system/user/page (带 Bearer token)
RT->>T: oauth2TokenApi.checkAccessToken(token) 查 Redis/MySQL
T-->>RT: 有效 → 组装 LoginUser(id,userType,tenantId,scopes,info)
RT->>SC: SecurityFrameworkUtils.setLoginUser → 放入 SecurityContext
RT->>SC: 交给 @PreAuthorize("@ss.hasPermission('system:user:query')")
SC->>SC: SecurityFrameworkServiceImpl → PermissionApi 校验权限
SC-->>U: 有权限 → Controller 正常返回;无权限 → 403 FORBIDDEN
这条链路串起了一个项目最核心的四个要素:统一返回(CommonResult)、认证(Token)、授权(@PreAuthorize 权限注解)、数据访问。跑通它,就等于跑通了”用一个平台做出来的系统”的标准请求形态。
场景 B:一行配置开启「多租户」,SQL 自动带上 tenant_id
SaaS 多租户是横切关注点的典型代表。yudao-spring-boot-starter-biz-tenant 通过一个 MyBatis 拦截器 + 线程上下文,让业务代码一行都不用改就自动按租户隔离数据。逐行原理见 第六章 Redis 与多租户。高层流程图:
flowchart LR
A[HTTP 请求] --> B[TenantSecurityWebFilter]
B --> C{URL 是否在 ignore-urls?}
C -- 是 --> F[不解析租户,直接放行]
C -- 否 --> D[从 Header 'tenant-id' 解析租户编号]
D --> E[写入 TenantContextHolder 线程上下文]
E --> G[Service 执行 SQL]
G --> H[TenantDatabaseInterceptor 拦截 SQL]
H --> I[自动给主表追加 tenant_id = ?]
I --> J[ORM 查询自动按租户隔离]
4. 架构全景图
4.1 Maven 多模块工程结构
graph TD
subgraph POM[根工程 yudao - pom]
DEP[yudao-dependencies BOM
统一管理依赖版本]
FW[yudao-framework 框架扩展]
SVR[yudao-server 服务端组装]
MOD[yudao-module-* 业务模块]
MODSM[system 系统]
MODIN[infra 基础设施]
MODOT[其余 bpm/pay/mall... 默认关闭]
end
DEP -.依赖管理.-> FW
FW --> SVR
MOD --> SVR
MODSM --> FW
MODIN --> FW
MODOT -.按需开启.-> FW
FW -.内置.-> COMM[common 基础类]
FW -.内置.-> SEC[security 安全 Starter]
FW -.内置.-> WEB[web Web Starter]
FW -.内置.-> MYB[mybatis 数据 Starter]
FW -.内置.-> RED[redis 缓存 Starter]
FW -.内置.-> TEN[tenant 多租户 Starter]
4.2 请求分层(三层架构 + API 边界)
graph LR
subgraph 表示层[Controller 层]
CT[xxxController]
end
subgraph 应用层[Service 层]
SV[xxxService / xxxServiceImpl]
end
subgraph 数据层[DAL 数据访问层]
MPR[xxxMapper]
DO[xxxDO 实体]
end
subgraph 内部[Api 接口层]
API[xxxApi 跨模块接口]
API_IMPL[xxxApiImpl 实现]
end
CT --> SV
SV --> MPR
MPR --> DO
SV -.跨模块调用.-> API
API --> API_IMPL
API_IMPL -.反查其他模块 Service.-> SV
关键约定:跨模块(例如 framework 需要 system 的权限、infra 需要 system 的日志)绝不直接依赖对方的 Service 类,而是定义 xxxApi 接口 + xxxApiImpl 实现,接口放在 *-api 子工程,实现放在 *-biz。这样模块之间只依赖接口,避免了”组播核爆炸”似的强耦合。
4.3 一次 CRUD 的代码形态(约定优于配置)
为了让读者对”一个标准功能长什么样”有肌肉记忆,这里以 system 模块的用户管理为模板示意(逐行版见 第八章):
1 | Controller → 接收请求、参数校验(@Valid)、注解式权限(@PreAuthorize)、返回 CommonResult |
5. 学习路线图
本学习文档共 11 章,建议按以下顺序阅读。前 6 章是地基(框架层),第 7~10 章是业务模块如何站在这块地基上,第 11 章是动手实践。
| 章节 | 主题 | 难度 | 前置 |
|---|---|---|---|
| 01 Maven 多模块工程结构 | 模块划分、-api/-biz、依赖治理 |
★ | 无 |
| 02 错误码与统一返回 | CommonResult、ErrorCode、异常体系、工具类 |
★ | 无 |
| 03 Web 请求层 | 全局异常处理、请求体包装、MVC 配置 | ★ | 02 |
| 04 安全与鉴权 | Token 认证、Spring Security、权限注解 | ★★★ | 02、03 |
| 05 MyBatis 数据层 | BaseDO、字段填充、数据权限、分页 |
★★ | 02 |
| 06 Redis 与多租户 | 缓存、TenantContextHolder、SQL 拦截 |
★★★ | 04、05 |
| 07 登录全流程 | 认证垂直切片(Auth→OAuth2 Token) | ★★★ | 04 |
| 08 系统模块与 RBAC | 用户/角色/菜单/字典/部门 + DAL 分层 | ★★ | 07 |
| 09 代码生成器 | 一键生成前后端代码的原理 | ★★★ | 08 |
| 10 Server 组装与应用时序 | 模块如何合成一个可启动的应用 | ★ | 全部 |
| 11 搭建与复刻指南 | 从零把这套平台跑起来 / 复刻 | ★ | 全部 |
6. 名词速查(贯穿全篇的锚点)
- 📍 源码根:
../../source/ruoyi-vue-pro-master/(下文简称 「源码根」) CommonResult定义见 CH02 §3BaseDO定义见 CH05 §4- 全局错误码表见 CH02 §4
💡 给读者的建议:不要试图一口气读完 11 章。每读一章,动手在该章源码根目录下打开对应文件跟读一遍。读到 第七章 时,建议配合浏览器(或 Postman)实际打一次登录接口,把” token 从哪来、被谁消费”这件事亲眼验证。