第五章. 后端项目结构深度解析:RuoYi-Vue-Plus 5.x 模块化实践

第五章. 后端项目结构深度解析:RuoYi-Vue-Plus 5.x 模块化实践

摘要:本章我们将深入 RuoYi-Vue-Plus 5.x 版本的“血肉”——后端项目结构。我们将从 4.x 的演进开始,逐层解构 5.x 的四大核心模块(Admin, Common, Modules, Extend),清晰理解其“高内聚、低耦合”的设计哲学,并为你建立清晰的二次开发蓝图。


本章学习路径

在深入代码之前,清晰的蓝图至关重要。我们将按照以下路径,逐层剥开 RuoYi-Vue-Plus 5.x 的后端架构:

后端项目结构深度解析

学习建议

  • 本章是后续所有后端开发的“地图”。请重点理解 5.x 分层设计的 目的,尤其是 ruoyi-commonruoyi-modules 的职责划分,这将直接决定你未来扩展功能的代码质量。

5.1. 架构演进:从 4.x “平铺”到 5.x “分层”

在上一章,我们已经彻底解析了 RuoYi-Vue-Plus 5.x 版本的核心数据库表结构,理解了 RBAC 权限模型和多租户的数据基础。但数据表只是“骨架”,这些数据是如何通过代码组织起来,实现复杂业务逻辑的?为什么 5.x 版本的结构备受推崇?本节我们将从对比 4.x 版本的架构开始,为你揭示 5.x 版本“高内聚、低耦合”分层设计的核心思路。

5.1.1. 4.x 架构痛点:根目录臃肿与职责混淆

如果我们现在打开一个 4.x 版本的项目,会发现一个明显的特征:项目根目录是“平铺”的。

在 4.x 结构中,根目录下混合了 ruoyi-common(通用模块)、ruoyi-system(系统模块)、ruoyi-generator(代码生成)、ruoyi-quartz(定时任务)、ruoyi-oss(对象存储)等十几个模块。

这种“平铺”结构在项目初期看似扁平,但随着功能迭代,会暴露三大痛点:

  1. 根目录臃肿:每增加一个功能模块(如短信、支付),根目录就增加一个模块,导致项目结构迅速膨胀,查找和管理变得混乱。
  2. 职责混淆ruoyi-system 这样的核心业务模块,与 ruoyi-common 这样的通用功能模块,以及 ruoyi-framework 这样的框架支撑模块全部混杂在同一层级,模块的职责定位不清晰。
  3. 依赖关系混乱:由于模块划分不清晰,很容易出现模块间不合理的交叉依赖,使得项目耦合度增高,难以维护和扩展。

5.1.2. 5.x 四层架构总览:Admin, Common, Modules, Extend

为了解决 4.x 的痛点,RuoYi-Vue-Plus 5.x 版本进行了一次彻底的架构重构,从“平铺”转向了“分层”。

5.x 版本引入了清晰的四层结构,将所有模块分门别类地归纳到四个“顶级目录”中,使得项目结构瞬间变得简洁、合理。

我们先来看一下 5.x 版本的根目录结构:

1
2
3
4
5
6
7
8
. 📂 RuoYi-Vue-Plus
├── 📄 pom.xml # 1. 父 POM,管理所有依赖
├── 📂 ruoyi-admin/ # 2. 主入口模块 (Web 启动层)
├── 📂 ruoyi-common/ # 3. 插件化核心 (通用功能层)
├── 📂 ruoyi-modules/ # 4. 业务模块组 (业务逻辑层)
├── 📂 ruoyi-extend/ # 5. 扩展服务模块 (独立服务层)
├── 📂 script/ # 6. 运维脚本
└── ... (其他根目录文件)

这四大核心模块各司其职,构成了 5.x 架构的基石:

模块名核心职责包含内容示例
ruoyi-admin聚合与启动唯一的 Web 服务启动入口。负责聚合所有模块,以及提供登录、验证码等门户接口。
ruoyi-common插件化核心高复用、低耦合 的通用功能。如 common-mybatiscommon-rediscommon-satoken 等。
ruoyi-modules业务模块组高内聚、低复用 的业务逻辑。如 modules-system (系统)、modules-generator (代码生成)。
ruoyi-extend扩展服务独立部署 的“卫星”服务。如 extend-monitor (监控中心)、extend-snailjob-server (调度中心)。

通过这种分层设计,5.x 版本完美解决了 4.x 的问题:

  • 臃肿? 不再臃肿。所有功能被清晰归类到 commonmodulesextend 中。
  • 混淆? 职责清晰。common 负责通用能力,modules 负责业务实现。
  • 混乱? 依赖清晰。admin 依赖 modulesmodules 依赖 common,依赖链条清晰可控。

5.1.3 本节小结

我们理解了 RuoYi-Vue-Plus 5.x 架构重构的动因,这是后续所有开发的基础:

  • 4.x 架构是“平铺式”的,在项目迭代中会暴露 根目录臃肿职责混淆依赖混乱 三大痛点。
  • 5.x 架构重构为“分层式”,极大提升了模块的内聚性、可维护性和扩展性。
  • 5.x 的四大核心模块是:ruoyi-admin (入口)、ruoyi-common (通用插件)、ruoyi-modules (业务功能)、ruoyi-extend (扩展服务)。

5.2. 主入口模块 (ruoyi-admin):聚合与启动

在上一节中,我们已经清晰了 5.x 版本“分层式”的四大核心模块。但在实际运行中,这四大模块并不是孤立的,它们需要一个“集结点”来将所有功能聚合在一起,并作为统一的服务启动。本节我们将深入剖析这个“集结点”——ruoyi-admin 模块,理解它作为项目唯一 Web 入口的核心职责。

5.2.1. 模块职责:唯一的 Web 服务入口

ruoyi-admin 模块是整个 RuoYi-Vue-Plus 后端应用的 唯一启动入口聚合器

它的核心职责有三个:

  1. 功能聚合:它在 pom.xml 中(Maven 构建配置文件)依赖了 ruoyi-modules(所有业务)和 ruoyi-common(所有插件)。这使得 ruoyi-admin 成为一个“主应用”,它将所有分散的业务模块和功能插件“打包”成一个可独立部署的 Spring Boot 应用。
  2. 提供启动:它包含了 DromaraApplication.java,这是整个项目的主启动类。我们运行后端服务时,启动的就是这个类。
  3. 充当门户:它只负责处理最前端的“门户”请求,如用户登录、注册、获取验证码等。所有具体的业务请求(如用户管理、部门管理)都会被路由到 ruoyi-modules 中的相应模块进行处理。

这种设计将“启动和门户”的职责与“具体业务”的职责彻底分离,使得 ruoyi-admin 自身非常轻量,只做一个“聚合者”和“看门人”的角色。


5.2.2. Spring Boot 如何“粘合”所有模块

在 5.2.1 节,我们说 ruoyi-admin 是“聚合器”。但这个词很抽象。

让我们面对一个更具体的问题:ruoyi-modules-system 模块定义了 SysUserController (用户控制器),而 ruoyi-common-redis 模块定义了 RedisUtils (缓存工具类)。这两个模块是 完全独立 的,它们甚至“不知道”对方的存在。

那么,为什么我们启动 ruoyi-admin 后:

  1. 浏览器能访问到 system 模块的 /system/user/list 接口?
  2. SysUserController 为什么能成功 Inject (注入) 并使用 RedisUtils
  3. 最后 ruoyi-admin 是如何把这几十个模块打包成一个 jar 文件部署的?

答案藏在 MavenSpring Boot 的两大核心机制中:① Maven 依赖传递② Spring Boot 自动装配

阶段一:Maven 依赖传递(“聚合”的蓝图)

我们首先要看的不是 Java 代码,而是 ruoyi-admin/pom.xml。这是“聚合”的第一步,它负责 收集所有“零件”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<description>web服务入口</description>

<dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-job</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-generator</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-demo</artifactId>
</dependency>

<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-doc</artifactId> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-social</artifactId> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-ratelimiter</artifactId> </dependency>

</dependencies>

核心原理:
ruoyi-adminpom.xml 就像一张“装配蓝图”。

  1. 收集零件:当你写下 <dependency> 时,你就是在告诉 Maven:“请去仓库把 ruoyi-system.jarruoyi-job.jarruoyi-common-doc.jar 等所有这些‘零件包’都下载到我本地。”
  2. 依赖传递:更关键的是,Maven 会打开 ruoyi-system.jarpom.xml,发现它依赖了 ruoyi-common-redis.jarruoyi-common-mybatis.jar。于是,Maven 会 自动地 把这些“零件的零件”也一起下载下来。
  3. 构建 Classpath:最终,当 ruoyi-admin 模块被编译和运行时,Maven 会把 所有(包括直接和间接)下载的 jar 文件,全部放入 Java 的 Classpath(类路径)中。

通俗理解Classpath 就像一个“大工具箱”。ruoyi-admin 通过 pom.xml 告诉 Maven:“把我需要的 system 业务包、job 业务包、redis 工具包、mybatis 工具包…全部扔进这个大工具箱里。”

此时,SysUserController.classRedisUtils.class 就被“扔”进了同一个工具箱,它们“物理上”已经在一起了。

阶段二:Spring Boot 自动装配(“粘合”的魔法)

现在所有“零件”都在工具箱(Classpath)里了,但它们还是零散的。SysUserController 怎么“认识”并“用上” RedisUtils 呢?

这就是 ruoyi-admin唯一 的 Java 启动类 DromaraApplication.java 的魔力所在。

1
2
3
4
5
6
7
8
9
// 路径: ruoyi-admin/src/main/java/org/dromara/DromaraApplication.java
@SpringBootApplication // 重点:这就是“魔法”的开关
public class DromaraApplication {
public static void main(String[] args) {
// SpringApplication.run 触发“自动装配”
SpringApplication.run(DromaraApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ RuoYi-Vue-Plus 启动成功 ლ(´ڡ`ლ)゙");
}
}

核心原理:
@SpringBootApplication 是一个复合注解,它最重要的能力之一来自 @EnableAutoConfiguration (启用自动装配)。

SpringApplication.run 启动时,@EnableAutoConfiguration 会执行一个关键动作:

  1. 扫描 Classpath:它会 扫描 我们在阶段一构建的那个“大工具箱”(Classpath)里 所有jar 包。
  2. 寻找“装配说明书”:它专门寻找一个名为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 的文件。(在 ruoyi-common 插件中,你可以在 target/classes 目录下找到它)。
  3. 加载配置
    • Spring Boot 在 ruoyi-common-redis.jar 里找到了这个文件,文件里写着:“请加载 org.dromara.common.redis.config.RedisConfig”。
    • Spring Boot 在 ruoyi-common-mybatis.jar 里也找到了,文件里写着:“请加载 org.dromara.common.mybatis.config.MybatisPlusConfig”。
    • Spring Boot 在 ruoyi-modules-system.jar找不到 这个文件,因为它是一个业务模块,它只 使用 配置,不 提供 配置。
  4. 按需实例化
    • Spring Boot 加载 RedisConfig。这个类里面写着:“@Bean: 创建一个 RedisUtils 实例,并把它注册到 Spring 容器(IOC)中”。
    • Spring Boot 加载 MybatisPlusConfig,它创建并注册了“分页插件”、“数据权限插件”等实例。
  5. 依赖注入(粘合!)
    • 最后,Spring Boot 开始扫描 ruoyi-modules-system.jar 里的 SysUserController
    • SysUserController 说:“我需要 @Autowired private RedisUtils redisUtils;”。
    • Spring 容器说:“没问题!RedisConfig 刚刚注册了一个 RedisUtils 实例,我把它‘注入’给你。”

至此,“粘合”完成ruoyi-admin 模块 一行代码都没写,但它通过 Spring Boot 的自动装配机制,成功地让 system 模块用上了 common-redis 模块的功能。

阶段三:Spring Boot 打包插件(“封装”的成品)

现在我们理解了“聚合”和“粘合”。最后一个问题是:如何把这个由几十个 jar 组成的“大工具箱”变成一个 可执行的单一的 ruoyi-admin.jar 文件,方便我们部署到服务器?

这就要看 ruoyi-admin/pom.xml<build> 部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

核心原理:
spring-boot-maven-pluginrepackage 目标会执行一个特殊操作,它生成的不是一个普通的 jar,而是一个“Fat JAR”(胖包)。

  1. “胖”在哪里?:这个插件会 解压 所有在阶段一收集到的 jar 包(如 ruoyi-system.jar, ruoyi-common-redis.jar, 甚至 spring-boot-starter-web.jar),把它们所有的 .class 文件和资源文件,按照 相同的目录结构全部复制ruoyi-admin.jar 内部的 BOOT-INF/classes 目录下。
  2. 启动器:它还会在 jar 包里塞入 Spring Boot 的 启动加载器org.springframework.boot.loader)。

最终结果:我们得到的 ruoyi-admin.jar 文件(通常几十上百 MB),它内部已经包含了 所有模块.class 文件。它不再依赖外部任何 jar

当我们执行 java -jar ruoyi-admin.jar 时:

  1. Spring Boot 的 启动加载器 首先运行。
  2. 它会把 BOOT-INF/classes 目录(包含了所有模块的代码)加载到 Classpath 中。
  3. 然后它调用 DromaraApplicationmain 方法。
  4. 后续流程回到 阶段二@SpringBootApplication 开始自动装配,粘合所有功能,项目成功启动。

5.2.3. 本节小结

我们深入探究了 ruoyi-admin 模块,它是整个项目的“心脏”和“门户”:

  • 核心定位ruoyi-admin 是项目 唯一的 Web 启动入口功能聚合器
  • 聚合蓝图(Maven):通过 pom.xml<dependency> 收集所有 modules(业务)和 common(插件)模块,并将它们(通过依赖传递)全部放入 Classpath(类路径)中。
  • 粘合机制(Spring Boot)DromaraApplication@SpringBootApplication 注解会触发 自动装配,扫描 Classpath 中所有 common 插件的“装配说明书”(AutoConfiguration.imports),自动实例化 RedisUtils 等工具 Bean,并将其 注入system 等业务模块中。
  • 打包成品(Fat JAR)spring-boot-maven-plugin 插件将所有模块的 .class 文件解压并 重新打包 到一个 可执行的 ruoyi-admin.jar 中,实现单一文件部署。

5.3. 插件化核心 (ruoyi-common):解耦与复用

在上一节中,我们深入分析了 ruoyi-admin 模块,明确了它是聚合所有功能并提供 Web 启动的唯一入口。我们知道了 admin 模块的 pom.xml (Maven 配置文件) 会依赖所有业务与插件。但这引出了一个新的问题:那些被 admin 聚合的“通用功能”(如 Redis、MyBatis、Sa-Token)是如何被组织的?本节我们将深入探索 RuoYi-Vue-Plus 5.x 架构的“弹药库”——ruoyi-common 模块,理解其“一切皆插件”的低耦合设计哲学。

5.3.1. 设计哲学:“一切皆插件”的低耦合实践

ruoyi-common 模块的设计思想是对 4.x 版本的重大革新。在 4.x 中,ruoyi-common 是一个庞大、臃肿的“工具包”,包含了各种各样的工具类、常量和配置,导致所有模块都必须依赖这个庞大的“黑盒”。

5.x 的设计哲学是“高内聚、低耦合、可插拔”。

它将 4.x 中那个庞大的 common 模块,彻底拆分成了 20+功能单一、职责清晰 的微型子模块。

  • 设计原则:RuoYi-Vue-Plus 5.x 认为,“我只提供我需要的功能”。如果一个业务模块(比如 ruoyi-modules-system)只需要 Redis 和 MyBatis,它就不应该被迫引入 Excel、OSS 或 Mail 的任何代码。
  • 实现方式ruoyi-common 里的每一个子模块,如 ruoyi-common-redisruoyi-common-mybatis,都是一个功能完备的“微型 Spring Boot Starter”。它们利用 Spring Boot 的自动装配(AutoConfiguration)机制,只要被业务模块在 pom.xml 中引入,就能自动启用相应功能。
  • 带来的价值
    1. 高度解耦:模块间不再有不必要的依赖。
    2. 易于维护:每个子模块代码量极少,职责单一,修改和升级非常容易。
    3. 防止循环依赖:清晰的单向依赖(业务模块 -> Common 插件)从根本上避免了代码腐化。

5.3.2. 基石:common-bom (版本声明) 与 common-core (核心工具)

ruoyi-common 目录下的 20 多个子模块中,有两个模块是整个体系的基石,必须优先理解:

1
2
3
4
5
6
7
📂 ruoyi-common/
├── 📄 pom.xml
├── 📂 ruoyi-common-bom/ # 1. 版本声明中心
├── 📂 ruoyi-common-core/ # 2. 核心工具包
├── 📂 ruoyi-common-doc/ # ...
├── 📂 ruoyi-common-encrypt/ # ...
└── ... (其他 20+ 插件)
  1. ruoyi-common-bom (Bill of Materials)

    • 定位:版本仲裁中心。bom 是一个 Maven 术语,全称是 “Bill of Materials”。
    • 职责:这个模块 不包含任何 Java 代码。它的 pom.xml 文件使用 <dependencyManagement> 标签,统一声明 了所有 ruoyi-common-* 子模块的版本号。
    • 目的:确保整个项目在引用任何 common 插件时,版本都是一致的,避免了版本冲突。其他模块(如 ruoyi-modules-system)在引入 common 插件时,只需指定 groupIdartifactId,无需关心版本号,版本由 bom 统一管理。
  2. ruoyi-common-core (核心工具包)

    • 定位:框架的“最小功能集”。
    • 职责:它提供了整个应用 必须 的、最基础 的公共类。这包括:
      • R.java:统一的响应结果封装。
      • BaseEntity.java:基础实体类(包含 createBy, createTime 等)。
      • GlobalConstants.java:全局常量。
      • LoginUser.java:登录用户信息模型。
      • SpringUtils.java / StringUtils.java:常用的工具类。
      • 全局异常、基础配置(如线程池)等。
    • 目的common-core 是唯一一个 几乎所有 其他 common 插件和 modules 业务模块都 必须依赖 的模块。它抽离了最通用的代码,避免了重复定义。

5.3.3. 核心插件归类导览(数据、安全、Web、工具)

理解了 bomcore 之后,ruoyi-common 下的其他 20 多个模块就非常容易理解了。它们是按需取用的“功能插件”,我们可以将它们分为四大类:

1. 数据与持久化插件

  • ruoyi-common-mybatis:集成 MyBatis-Plus,提供数据权限、分页插件、自动填充等数据库核心功能。
  • ruoyi-common-redis:集成 Redisson,提供 RedisUtils 工具类和 Spring Cache 缓存实现。
  • ruoyi-common-encrypt:提供数据库字段 自动加解密 功能(基于 EncryptField 注解)。
  • ruoyi-common-sensitive:提供 数据脱敏 功能(基于 Sensitive 注解),如对手机号、身份证进行自动遮蔽。
  • ruoyi-common-translation:提供 通用翻译 能力(基于 Translation 注解),能在返回 JSON 时自动将“用户 ID”翻译为“用户昵称”,或“OSS ID”翻译为“图片 URL”。
  • ruoyi-common-tenant:提供多租户(Tenant)插件,实现基于 MyBatis-Plus 的数据隔离。

2. 安全与鉴权插件

  • ruoyi-common-satoken:集成 Sa-Token 权限框架,提供登录鉴权、权限校验(@SaCheckLogin)等服务。
  • ruoyi-common-security:安全模块,主要用于配置 URL 拦截规则(如哪些路径需要登录、哪些路径公开)。
  • ruoyi-common-idempotent:防重提交(幂等性)插件(基于 RepeatSubmit 注解),防止前端快速点击造成数据重复。
  • ruoyi-common-ratelimiter:接口限流插件(基于 RateLimiter 注解),可防止接口被高频访问或爬虫攻击。

3. Web 与通信插件

  • ruoyi-common-web:提供 Web 服务所需的基础设施,如全局异常处理、XSS 过滤器、国际化(i18n)配置等。
  • ruoyi-common-doc:集成 SpringDoc,用于自动生成 Swagger API 文档。
  • ruoyi-common-log:提供操作日志(@Log 注解)的 AOP(面向切面编程)实现。
  • ruoyi-common-social:集成 JustAuth,提供第三方登录(如微信、QQ、Gitee)功能。
  • ruoyi-common-sse:提供 SSE (Server-Sent Events) 流式推送功能,替代 WebSocket 实现轻量级消息推送。
  • ruoyi-common-websocket:提供 WebSocket 长连接通信支持。

4. 业务与工具插件

  • ruoyi-common-excel:集成 EasyExcel,提供强大的 Excel 导入导出功能(基于 @Excel 注解)。
  • ruoyi-common-oss:提供对象存储(OSS)的统一接口,支持 Minio、阿里云、腾讯云等多种存储。
  • ruoyi-common-job:集成 SnailJob,作为任务调度的 客户端(Client)注册到调度中心。
  • ruoyi-common-mail:邮件发送工具。
  • ruoyi-common-sms:短信发送工具。
  • ruoyi-common-json:提供基于 Jackson 的 JSON 序列化/反序列化配置。

当我们需要为项目封装一个新的“通用功能”(比如集成“Elasticsearch 搜索”)时,最佳实践就是模仿 ruoyi-common,在此目录下创建一个 ruoyi-common-es 子模块,将其封装为一个可插拔的“微型 Starter”。


5.3.4. 本节小结

我们详细解构了 ruoyi-common 模块,它是 5.x 架构实现“低耦合”的关键:

  • 设计哲学:从 4.x 的“大黑盒”演变为 5.x 的“一切皆插件”,每个插件都是一个功能单一、可插拔的“微型 Starter”。
  • 两大基石common-bom 负责统一版本管理;common-core 提供所有模块必需的最小功能集(如 R.java)。
  • 四大分类:所有插件可归为 数据持久化(MyBatis, Redis…)、安全鉴权(Sa-Token, RateLimiter…)、Web 通信(Web, Doc, SSE…)和 业务工具(Excel, OSS, Job…)。
  • 开发规范common 模块只封装 通用能力,不应包含任何具体业务逻辑(如对 SysUser 表的直接操作)。

5.4. 业务模块组 (ruoyi-modules):隔离与专注

在上一节中,我们彻底解构了 ruoyi-common 插件化仓库,理解了它如何将通用功能(如 Redis、MyBatis)封装为可插拔的“微型 Starter”。我们知道了 ruoyi-admin 如何聚合这些插件来实现启动。但一个企业级应用的核心——业务逻辑(如用户管理、部门管理、订单处理)——显然不应该放在 common(通用工具)或 admin(启动入口)中。

那么,这些 高内聚 的业务功能被存放在哪里?本节我们将深入探讨四大模块中的“业务中心”——ruoyi-modules 模块组,理解它是如何实现业务隔离与专注的。

5.4.1. 模块职责:业务功能的“高内聚”容器

ruoyi-modules 模块组是 5.x 架构中 所有业务逻辑的容器”。

它的设计哲学与 ruoyi-common 截然相反:

  • ruoyi-common 追求 低耦合、高复用(工具必须被大家用)。
  • ruoyi-modules 追求 高内聚、低复用(业务必须独立不串扰)。

“高内聚” 意味着一个模块只做一件事,并把它做好。例如,system 模块只负责权限、用户、菜单等系统基础业务;它绝对不会关心“代码生成”或“定时任务”的具体逻辑。

这种设计的核心价值在于 隔离

  1. 业务隔离:当你修改“系统管理”的业务逻辑时,你完全不必担心会影响到“代码生成”模块。
  2. 开发隔离:团队可以并行开发,A 团队负责 modules-system,B 团队负责 modules-mall(商城模块),互不干扰。
  3. 扩展性:当需要新增一个“订单业务”时,只需在 ruoyi-modules 下新建一个 ruoyi-modules-order 模块即可,对现有代码零侵入。

5.4.2. 内置业务模块:system, generator, job

让我们打开 ruoyi-modules 目录,看看它内置了哪些业务模块:

1
2
3
4
5
6
📂 ruoyi-modules/
├── 📄 pom.xml # 1. 模块组的父 POM
├── 📂 ruoyi-demo/ # 2. 官方演示模块(二次开发范本)
├── 📂 ruoyi-generator/ # 3. 代码生成模块
├── 📂 ruoyi-job/ # 4. 定时任务业务
└── 📂 ruoyi-system/ # 5. 核心系统模块
  1. ruoyi-system (核心系统模块)

    • 这是整个后台 最核心的业务模块,没有之一。
    • 它实现了我们在第四章所分析的 RBAC 权限模型,包含了对 sys_user, sys_role, sys_menu, sys_dept 等核心表的所有业务操作(Controller, Service, Mapper)。
    • 此外,系统配置、字典管理、多租户管理、OSS 配置管理等基础业务也都在这里。
  2. ruoyi-generator (代码生成模块)

    • 负责实现“代码生成”功能。它会读取数据库表结构,根据模板(Velocity)生成对应的前后端 CURD 代码。
  3. ruoyi-job (定时任务业务)

    • 注意:这个模块与 ruoyi-extend 中的 ruoyi-snailjob-server(调度中心)不同。
    • ruoyi-job 扮演的是 任务执行者(Client) 的角色。它定义了“具体要执行哪些业务定时任务”(例如 AlipayBillTask.java 支付宝对账任务)。
    • 它依赖 ruoyi-common-job 插件来将自己注册到 snailjob-server 调度中心。
  4. ruoyi-demo (官方演示模块)

    • 这是一个“教科书”式的功能演示,展示了如何在 RVP 框架下正确地使用各种 common 插件(如 Excel 导入导出、Redis 分布式锁、数据脱敏等)。

5.4.3. 二次开发范本:ruoyi-demo

ruoyi-demo 模块是 RVP 留给我们的最佳规范。当我们需要进行二次开发(例如新增一个“商城模块”)时,最规范的路径 就是 完整复制 ruoyi-demo,并将其重命名(例如 ruoyi-mall),然后在此基础上进行开发。

一个标准的二次开发流程如下:

第一步:创建新业务模块
ruoyi-modules 目录下,复制 ruoyi-demo 并重命名为 ruoyi-mall

第二步:修改 ruoyi-mall/pom.xml
修改 artifactIdruoyi-mall,并根据你的业务需求,按需引入 ruoyi-common 插件。

1
2
3
4
5
6
7
8
9
10
11
12
13
<parent>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-modules</artifactId> <version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-mall</artifactId> <dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-redis</artifactId> </dependency>
</dependencies>

第三步:在 modules 父 POM 中声明
ruoyi-modules/pom.xml 中,注册这个新的子模块。

1
2
3
4
5
6
<modules>
<module>ruoyi-system</module>
<module>ruoyi-generator</module>
<module>ruoyi-job</module>
<module>ruoyi-demo</module>
<module>ruoyi-mall</module> </modules>

第四步:在 admin 主入口中聚合
这是最关键的一步。admin 模块是主启动器,它必须“知道” ruoyi-mall 模块的存在,才能扫描到它的组件。

1
2
3
4
5
<dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-mall</artifactId> </dependency>
</dependencies>

完成这四步,ruoyi-mall 模块就成功集成到了 RVP 体系中。启动 ruoyi-admin 时,Spring Boot 会自动扫描 ruoyi-mall 中的所有 Controller、Service 等,使其成为应用的一部分。


5.4.4. 本节小结

我们深入了解了 ruoyi-modules 模块组,它是所有业务逻辑的“家”:

  • 核心定位ruoyi-modules 是业务功能的“高内聚”容器,追求业务隔离,与 ruoyi-common(高复用工具)职责完全不同。
  • 内置模块ruoyi-system(核心权限业务)、ruoyi-generator(代码生成)、ruoyi-job(业务任务定义)以及 ruoyi-demo(最佳实践范本)。
  • 二次开发:标准流程是 复制 ruoyi-demo,重命名为你自己的业务模块(如 ruoyi-mall),并在 ruoyi-modules/pom.xmlruoyi-admin/pom.xml 中同时注册该新模块。

5.5. 扩展服务模块 (ruoyi-extend):独立部署与运维

在上一节中,我们深入剖析了 ruoyi-modules 模块组,明确了它是所有核心 业务逻辑(如 system, generator)的“高内聚”容器,这些模块最终会被 ruoyi-admin 聚合打包成一个单体应用。但在我们的项目结构中,还存在一个 ruoyi-extend 目录,它包含了 ruoyi-monitor-admin(监控中心)和 ruoyi-snailjob-server(调度中心)。

这引出了一个关键的架构问题:为什么监控和任务调度 中心(Server)没有像 ruoyi-job(任务客户端)一样放在 ruoyi-modules 里被 admin 聚合?本节我们将为你揭示 ruoyi-extend 模块的设计哲学,理解其在分布式运维中的核心价值。

5.5.1. 模块职责:“卫星服务”与独立部署

ruoyi-extend 模块组的定位是“平台级卫星服务”。

它所包含的模块与 ruoyi-modules 中的业务模块有本质区别:

  • ruoyi-modules (业务模块)

    • 定位:主应用的“业务功能”。
    • 生命周期:与 ruoyi-admin 绑定,被 admin 聚合打包,随 admin 一同启动和停止。
    • 举例ruoyi-system (系统业务)。
  • ruoyi-extend (扩展服务)

    • 定位:主应用的“支撑平台”或“运维工具”。
    • 生命周期完全独立。它自己就是一个 可单独启动和部署 的 Spring Boot 应用,不被 admin 依赖。
    • 举例ruoyi-monitor-admin (监控服务)。

为什么要这样设计

在企业级生产环境中,将监控、调度中心这类“平台基础设施”与“业务应用”相剥离,是保证系统高可用的核心原则。

  1. 避免单点故障 (SPOF)
    • 场景:假设我们将“监控中心”和“业务应用”打包在一起。如果业务应用因 Bug 崩溃 (OOM),那么监控中心也随之宕机。
    • 结果:我们将 无法收到 任何关于“业务应用已宕机”的告警,因为监控服务自己也死了。这就是灾难性的“单点故障”。
  2. 隔离资源与生命周期
    • 资源隔离:监控和任务调度都是资源密集型服务(占用 CPU、内存、网络)。将它们独立部署,可以避免它们与核心业务(如 ruoyi-system)争抢同一个 JVM(Java 虚拟机)的资源。
    • 生命周期隔离:业务应用(ruoyi-admin)可能需要频繁更新迭代(每周发布)。而监控中心(ruoyi-monitor-admin)则追求高度稳定(数月才更新一次)。将它们分离,使得业务应用可以自由启停,而不影响监控平台的稳定运行。

5.5.2. 服务解析 (一):ruoyi-monitor-admin 监控中心

ruoyi-monitor-admin 是基于 spring-boot-admin (SBA) 框架构建的 监控服务端(Server)。

它的职责是提供一个 Web UI 界面,用于汇集、展示所有“客户端”上报的健康状态、JVM 指标、日志级别、API 列表等运维信息。

让我们看一下它的内部结构:

1
2
3
4
5
6
7
8
9
10
11
12
📂 ruoyi-extend/
└── 📂 ruoyi-monitor-admin/
   ├── 📄 pom.xml # 1. 依赖 spring-boot-admin-starter-server
   └── 📂 src/
       └── 📂 main/
           └── 📂 java/
               └── 📂 org/dromara/monitor/admin/
                   ├── 📄 MonitorAdminApplication.java # 2. 核心:独立的 Spring Boot 启动类
                   └── 📂 config/
                       └── 📄 SecurityConfig.java # 3. 监控中心自身的安全配置
           └── 📂 resources/
               └── 📄 application.yml # 4. 独立的配置文件(如端口 9090)

关键点

  • MonitorAdminApplication.java:它拥有 自己的 main 方法。这证明了它是一个可以 独立运行 的 Spring Boot 应用,而不是一个被 ruoyi-admin 依赖的库。
  • ruoyi-admin 的角色:与此相对,我们在 ruoyi-admin/pom.xml 中看到的依赖是 spring-boot-admin-starter-client(客户端)。
  • 主从关系ruoyi-admin (Client) 启动后,会主动向 ruoyi-monitor-admin (Server) 注册,并定时上报自己的心跳和指标。

5.5.3. 服务解析 (二):ruoyi-snailjob-server 调度中心

ruoyi-snailjob-server 是 SnailJob 分布式任务调度框架的 服务端(Server),即“调度中心”。

它的职责是提供一个 Web UI 界面,用于管理任务(如新增、触发、停止)、监控任务执行状态,并按照调度策略(如 CRON 表达式)向所有注册的“客户端”下发执行指令。

1
2
3
4
5
6
7
8
9
📂 ruoyi-extend/
└── 📂 ruoyi-snailjob-server/
   ├── 📄 pom.xml # 1. 依赖 snail-job-server-stand-alone
   └── 📂 src/
       └── 📂 main/
           └── 📂 org/dromara/snailjob/
               ├── 📄 SnailJobServerApplication.java # 2. 核心:独立的 Spring Boot 启动类
           └── 📂 resources/
               └── 📄 application.yml # 3. 独立的配置文件(如端口 8888)

关键点

  • SnailJobServerApplication.java:同样,它拥有 自己的 main 方法,是一个 独立部署 的服务。

  • ruoyi-modules-job 的关系:这是初学者 最容易混淆 的地方,必须厘清。这里有一个 90% 的人会混淆的细节:ruoyi-extend/ruoyi-snailjob-serverruoyi-modules/ruoyi-job 有什么区别?

  • ruoyi-extend/ruoyi-snailjob-server (调度中心 - Server)

    • 角色大脑。它只负责“管理和触发”任务,它 不包含 任何具体的业务逻辑。
    • 职责:它决定“谁(哪个客户端),在 什么时间(CRON),去 执行什么任务(JobName)”。
    • 部署:独立部署,高可用。
  • ruoyi-modules/ruoyi-job (任务业务 - Client)

    • 角色双手。它 不负责 调度,它只包含“具体要执行的业务代码”(如 AlipayBillTask.java 支付宝对账任务)。
    • 职责:它向 server 注册自己,然后“待命”,等待 server 发来“执行”指令后,才开始工作。
    • 部署:被 ruoyi-admin 聚合,随业务应用一同部署。

5.5.4. 本节小结

我们剖析了 ruoyi-extend 模块,理解了它作为“平台级卫星服务”的特殊定位:

  • 核心定位ruoyi-extend 存放 独立部署 的“支撑平台”,与 ruoyi-modules(业务功能)在架构上完全解耦。
  • 设计目的:为了 避免单点故障 (SPOF),实现 资源隔离生命周期隔离,这是保证生产环境高可用的关键。
  • 服务解析ruoyi-monitor-admin 是监控 服务端 (Server),而 ruoyi-admin 是客户端 (Client);ruoyi-snailjob-server 是调度 中心 (Server),而 ruoyi-modules-job 是执行 客户端 (Client)

实战蓝图 (二次开发指南)

  • 什么时候往 ruoyi-extend 添加模块?

    • 当你需要引入一个新的“平台级”中间件 服务端 时。
    • 示例:你想引入 Canal(MySQL 变更日志同步工具)的服务端,或者 Nacos(配置中心)的服务端。
  • 什么时候往 ruoyi-modules 添加模块?

    • 当你需要开发一个新的“业务功能”时。
    • 示例:开发“商城模块”、“订单模块”、“支付模块”。

思考检验

如果公司需要引入一套 ELK(Elasticsearch, Logstash, Kibana)日志平台,ELK 的服务端部署包应该放在 ruoyi-extend 还是 ruoyi-modules?业务应用(ruoyi-admin)中用于“上报日志”的 log-client 插件又应该放在哪里?

  1. ELK 服务端:不属于 RVP 项目的任何部分。ELK 自身是庞大且完全独立的服务集群,应由运维团队 单独部署 在服务器或 K8s 集群中。ruoyi-extend 存放的是 RVP 生态内的轻量级的 Spring Boot 扩展服务,而非重量级的第三方平台。
  2. log-client 插件:最佳实践是放在 ruoyi-common 模块下。
    • 原因:它是一个 高复用 的“通用功能”(common),而不是一个“业务”(modules)。我们应该将其封装为 ruoyi-common-logstashruoyi-common-elk 插件,让 ruoyi-modules 中的所有业务模块都能按需引入它,来实现日志上报。

5.6. 根目录文件与二次开发指南

在上一节中,我们清晰地区分了 ruoyi-extend(独立卫星服务)和 ruoyi-modules(核心业务逻辑)的定位。至此,我们已经完整探索了 admincommonmodulesextend 这四大 Java 模块组。然而,一个完整的企业级项目不仅仅只有 Java 代码,在项目的根目录下,还包含着一系列对依赖管理、运维部署和团队协作至关重要的“管家”文件。本节作为本章的收尾,我们将逐一解析这些根目录文件,为你扫清项目全局配置的最后障碍。

我们首先看一下 RVP 5.x 的完整根目录结构:

1
2
3
4
5
6
7
8
9
10
11
. 📂 RuoYi-Vue-Plus
├── 📄 LICENSE # 1. 开源协议
├── 📄 README.md # 2. 项目说明书
├── 📄 .editorconfig # 3. 编辑器风格配置
├── 📄 .gitignore # 4. Git 提交忽略配置
├── 📄 pom.xml # 5. 核心:父 POM (项目依赖基石)
├── 📂 ruoyi-admin/ # (已讲解) Web 入口
├── 📂 ruoyi-common/ # (已讲解) 通用插件
├── 📂 ruoyi-extend/ # (已讲解) 扩展服务
├── 📂 ruoyi-modules/ # (已讲解) 业务模块
└── 📂 script/ # 6. 运维脚本库

README.md 是项目说明书,我们重点解析其余 5 个关键部分。

5.6.1. 父 POM (pom.xml)

根目录的 pom.xml 是整个项目的 父 POM(Project Object Model,项目对象模型)。它是所有 ruoyi-xxx 模块(包括子模块)的“最高管理者”。

  • 核心职责:它的核心使命是实现 全局的依赖版本控制。如果没有它,ruoyi-system 依赖的 spring-boot (3.1.0)ruoyi-job 依赖的 spring-boot (3.1.1) 可能会产生版本冲突,导致灾难性的 NoSuchMethodError(方法未找到)错误。
  • 实现方式:它通过两大标签实现全局掌控:
    1. <modules>:声明它管理着 ruoyi-admin, ruoyi-common, ruoyi-extend, ruoyi-modules 这四大模块组。
    2. <dependencyManagement>声明(但 实际引入)所有核心依赖(如 spring-boot-dependencies, mybatis-plus-boot-starter)的 版本号
  • 工作机制:当子模块(如 ruoyi-system)需要使用 mybatis-plus-boot-starter 时,它在自己的 pom.xml 中只需声明 groupIdartifactId无需 指定 <version>。Maven 在解析时会自动“向上”查找父 POM 中 <dependencyManagement> 声明的版本(如 3.5.7),从而保证整个项目使用的版本绝对统一。

5.6.2. script 目录:运维与部署的“工具箱”

script 目录是项目的运维脚本库,它不包含任何 Java 代码,是纯粹为 部署和维护 服务的“工具箱”。

  • 核心职责:旨在提供“开箱即用”的部署能力,封装复杂的运维命令,降低项目交付和维护的门槛。
  • 内容解析
    • sql/:存放所有数据库初始化脚本(我们在第二章用过)、以及历个版本的 数据库升级脚本update/ 目录)。
    • docker/:提供了 docker-compose.yml 文件,允许开发和运维人员使用 Docker 一键启动 项目所需的基础环境(如 Nginx, Redis, MySQL)。
    • bin/:提供了 ry.sh (Linux/MacOS) 和 ry.bat (Windows) 脚本。这些脚本用于在服务器上方便地启动、停止、重启我们打包好的 ruoyi-admin.jar 等应用,而无需手写冗长的 java -jar 命令。
    • leave/:存放工作流(WarmFlow)相关的流程模型 JSON 文件。

5.6.3. 规范与协议:.editorconfig, .gitignore, LICENSE

这三个以 . 开头(或全大写)的文件,是保证项目 协作规范性法律合规性 的基石,对于团队开发至关重要。

  • LICENSE (开源协议)

    • 是什么:RuoYi-Vue-Plus 采用 MIT 协议。这是一个法律文件,定义了其他人如何使用这个项目的代码。
    • 为什么重要:MIT 是一种非常宽松的协议。它允许你自由地修改、分发甚至 商用。但它有一个 强制要求:你 必须 在你的项目中 保留原始的版权和许可声明(即这个 LICENSE 文件和代码中的作者注释)。你不能声称这是你原创的,并且原作者不承担任何因使用本项目而引起的法律责任。
  • .gitignore (Git 忽略文件)

    • 是什么:一个纯文本文件,用于告诉 Git 版本控制系统,哪些文件或目录 永远不要 被追踪或提交到代码仓库。
    • 为什么重要:防止将“垃圾文件”或“私有文件”提交到共享仓库。
    • 内容:主要忽略的是:
      • target/:Java 编译后的 .class.jar 文件。
      • .idea/*.iml:IntelliJ IDEA 的本地配置文件。
      • .log:运行时产生的日志文件。
      • application-dev.yml默认建议忽略。因为开发环境的数据库密码、Redis 密码通常是私有的,不应提交到公共仓库。
  • .editorconfig (编辑器配置)

    • 是什么:一个跨 IDE 和编辑器的配置文件。
    • 为什么重要强制统一团队所有成员的编码风格
    • 内容:它定义了诸如:
      • indent_style = space (缩进使用空格,而不是 Tab)
      • indent_size = 4 (缩进大小为 4 个空格)
      • charset = utf-8 (文件编码为 UTF-8)
    • 价值:避免 A 提交的代码是 2 空格缩进,B 提交的是 4 空格 Tab 缩进,导致代码格式混乱和无效的 Git 变更(Code Review 的灾难)。

5.6.4. 本节小结

我们完成了对根目录“管家文件”的解析:

  • pom.xml (父 POM):通过 <dependencyManagement> 统一管理 所有子模块 的依赖 版本,避免冲突。
  • script/:运维工具箱,包含 sql (数据库脚本) 和 docker (一键环境) 等。
  • LICENSE (MIT 协议):允许商用,但 必须保留 原始版权声明。
  • .gitignore必须配置。用于忽略 target/.idea/ 等本地文件,防止污染代码仓库。
  • .editorconfig:保证团队编码风格(如缩进、编码)的统一。

5.7.本章总结

第五章是 RuoYi-Vue-Plus 后端开发的“架构地图”。我们从 4.x 的“平铺”阵痛讲起,深入剖析了 5.x 版本“分层式”架构重构的精妙之处。

我们详细解构了四大模块组的核心职责:

  1. ruoyi-admin (聚合与启动):它是 唯一的 Web 入口。通过 Maven 依赖和 Spring Boot 自动装配,将所有 modulescommon 粘合、打包成一个可执行的 “Fat JAR”。
  2. ruoyi-common (插件化核心):它是“弹药库”,采用“一切皆插件”的设计哲学。将 Redis、MyBatis、Sa-Token 等通用能力封装为 高复用、低耦合 的“微型 Starter”。
  3. ruoyi-modules (业务模块组):它是“业务中心”,采用“高内聚、低复用”的设计哲学。systemgenerator 等业务模块在此隔离,二次开发时的新业务(如 ruoyi-mall)也应在此创建。
  4. ruoyi-extend (扩展服务):它是“卫星平台”,用于 独立部署 监控中心 (monitor) 和调度中心 (snailjob-server),通过 隔离部署 来保证主业务的高可用性。

最后,我们解析了根目录的“管家文件”(pom.xml, .gitignore 等),为团队协作和规范开发奠定了基础。

实战蓝图 (二次开发指南)

学完本章,我们必须建立清晰的二次开发蓝图。当你接到一个新需求时,你应该这样思考:

需求场景应该修改/添加到哪里?为什么?
1. 开发一个全新的“商城业务ruoyi-modules (新建 ruoyi-mall)业务功能,高内聚,应与 system 模块隔离。
2. 为商城业务集成“支付宝支付ruoyi-common (新建 common-alipay)支付是 通用能力mallorder 都可能用,应封装为 高复用 插件。
3. 修改“登录”接口的逻辑ruoyi-admin (修改 AuthController)admin 是 Web 门户,负责登录、验证码等“入口”请求。
4. 升级 MyBatis-Plus 版本pom.xml父 POM 的 <dependencyManagement> 统一管理全局版本。
5. 部署一台 Canal Server 同步数据ruoyi-extend (新建 extend-canal-server)Canal 是平台级“卫星服务”,应 独立部署,避免与主业务耦合。

知识盲点自查表

不看笔记,尝试回答以下问题,检验你对 5.x 架构的理解程度:

  1. (填空)5.x 四大模块组中,ruoyi-common 追求 _________,而 ruoyi-modules 追求 _________
  2. (填空)ruoyi-admin 是通过 Spring Boot 的 _________ 注解和 _________ 机制,来“粘合”所有 commonmodules 模块的。
  3. (判断)ruoyi-monitor-admin (监控中心) 和 ruoyi-snailjob-server (调度中心) 必须和 ruoyi-admin 打包在 一起 部署,这是对的吗?(请说明为什么
  4. (填空)如果我想新增一个“订单模块”,标准流程是复制 _________ 模块,重命名后,分别在 __________________ 两个 pom.xml 中注册依赖。
  5. (填空).gitignore 文件的核心作用是防止 __________________ 等本地文件污染代码库。
  1. ruoyi-common 追求 高复用、低耦合(插件化),而 ruoyi-modules 追求 高内聚、低复用(业务隔离)。
  2. @SpringBootApplication 注解 和 自动装配 (AutoConfiguration) 机制。
  3. 错误必须分开独立部署。这是 ruoyi-extend 模块的核心设计。如果打包在一起,一旦 ruoyi-admin 业务应用崩溃,监控和调度中心会随之宕机,导致 单点故障 (SPOF),无法实现告警和高可用。
  4. 复制 ruoyi-demo 模块,并在 ruoyi-modules/pom.xml(注册为子模块)和 ruoyi-admin/pom.xml(引入依赖)中注册。
  5. target/ (编译目录) 和 .idea/ (IDE 配置)。(或 .log 日志等)