第二十二章. Maven 架构:RVP 5.x 依赖管理与构建解析
第二十二章. Maven 架构:RVP 5.x 依赖管理与构建解析
Prorise第二十二章. Maven 架构:RVP 5.x 依赖管理与构建解析
摘要:本章我们将深入 RVP 5.x 架构的核心——pom.xml 文件。我们将逐一解析根 POM、dependencyManagement(依赖管理)、ruoyi-common-bom(物料清单)以及 spring-boot-maven-plugin(打包插件)的配置与协同工作机制,帮助你彻底理解 5.x 版本“优雅、简洁、易于维护”的 Maven 依赖管理哲学。
本章学习路径
我们将按照以下路径,从根配置到子模块,层层解开 RVP 5.x 的 Maven 架构:

22.1. 根 pom.xml:RVP 5.x 架构的“总指挥部”
在 RVP 5.x 的项目结构中,位于 RuoYi-Vue-Plus/pom.xml 的根 pom.xml 文件是整个项目的“总指挥部”。它不包含任何业务代码,其核心职责是 定义规范、聚合模块、管理环境。
22.1.1. 坐标 (GAV) 的身份标识
我们首先查看根 pom.xml 顶部的基础配置:
1 | <project ...> |
- GAV 坐标:
groupId,artifactId,version是 Maven 项目的唯一坐标。groupId:org.dromara,项目所属的组织。artifactId:ruoyi-vue-plus,项目名称。version:${revision},一个变量,我们将在 22.2 节深入解析。
<modelVersion>4.0.0</modelVersion>:指定了 Maven 的项目对象模型(POM)版本,固定为4.0.0。<packaging>pom</packaging>:[核心] 此标签声明了这是一个“父项目”。它的职责 不是 打包成jar或war,而是“聚合”与“管理”在<modules>标签中定义的子模块。
22.1.2. <modules>:聚合“四大模块”
packaging 为 pom 的项目,通过 <modules> 标签来指定它所管理的子模块:
1 | <modules> |
这四行配置与项目根目录下的四个核心文件夹一一对应。Maven 在构建根项目时,会根据这个列表,依次进入每个子模块目录执行构建。RVP 5.x 的分层架构(Web 入口、通用插件、扩展服务、业务模块)在 Maven 层面得到了清晰的体现。
22.1.3. <properties>:集中管理(一)
<properties> 标签是 RVP 5.x 优雅管理依赖的基石。它允许我们定义“变量”,然后在整个项目(包括所有子模块)中引用。
1 | <properties> |
这里定义了关键的环境和框架版本:
<java.version>17</java.version>:在<build>插件中会引用此变量,确保项目所有模块都使用 Java 17 进行编译。<spring-boot.version>3.5.7</spring-boot.version>:在<dependencyManagement>中会引用此变量,确保所有 Spring Boot 相关的依赖都使用3.5.7版本。
这种集中管理的方式,使得未来升级 Spring Boot 版本或 Java 版本时,只需修改根 pom.xml 中的这一行配置即可。
22.1.4. <properties>:集中管理(二)
<properties> 标签的另一个重要职责是统一管理所有第三方依赖的版本号。
1 | <properties> |
在 RVP 4.x 时代,这些版本号分散在各个子模块的 pom.xml 中,升级 sa-token 可能需要修改多个文件。
在 5.x 中,所有版本被集中定义在根 POM。任何子模块(如 ruoyi-demo)需要使用 hutool 时,只需引入 hutool 的 GAV,version 会自动从根 POM 继承,确保了 版本统一 并 极大简化了维护。
22.1.5. <profiles>:dev vs prod 环境隔离与激活
<profiles> 标签用于定义不同环境(如开发、生产)下的特定配置。
1 | <profiles> |
RVP 5.x 通过 profiles 实现了 Maven 构建环境与 Spring Boot 配置文件的联动:
<id>dev</id>:定义了dev环境。<activeByDefault>true</activeByDefault>:使dev成为默认激活的环境。在 IDEA 中打开项目时,此 profile 会被自动勾选。<properties><profiles.active>dev</profiles.active></properties>:[核心机制] 当devprofile 被激活时,Maven 会设置一个名为profiles.active的属性,其值为dev。- Spring Boot 联动:Spring Boot 的
application.yml文件会读取这个 Maven 属性(@profiles.active@),并将其作为spring.profiles.active的值,从而指示 Spring Boot 加载application-dev.yml配置文件。
22.2. [核心] 破解 RVP 5.x 版本管理(上):${revision}
在 22.1 节中,我们分析了根 pom.xml 的基础配置,并注意到 GAV (GroupId, ArtifactId, Version) 中的 <version> 被设置为了一个变量:${revision}。但在 4.x 版本的 RVP 中,版本号是“硬编码”在每一个子模块的 pom.xml 文件中的。本节我们将深入探讨 RVP 5.x 为什么要做出这种改变,以及 ${revision} 变量是如何生效的。
22.2.1. 4.x 时代的痛点:子模块版本号“硬编码”的维护难题
在 RVP 4.x 的架构中,每个子模块(如 ruoyi-admin, ruoyi-system)的 pom.xml 文件中,都明确地“硬编码”了自身的版本号,例如 <version>4.8.1</version>。
这种方式的 维护痛点 非常明显:当项目需要从 4.8.1 升级到 4.8.2 时,开发者必须 手动修改 所有子模块 pom.xml 文件中的 <version> 标签。在一个拥有几十个模块的大型项目中,这是一项繁琐且极易出错的工作。一旦遗漏了某个模块,就会导致父子模块版本不一致,引发严重的构建失败或依赖冲突。
22.2.2. 5.x 的解决方案:GAV 中的 <version>${revision}</version>
RVP 5.x 彻底解决了这个痛点。在根 pom.xml (RuoYi-Vue-Plus/pom.xml) 中,我们看到:
1 | <groupId>org.dromara</groupId> |
它使用了 Maven 的属性占位符 ${revision} 作为版本号。更重要的是,所有子模块(如 ruoyi-admin)都从这个根 POM 继承:
1 | <parent> |
通过这种方式,所有模块的版本号都 唯一 指向了根 POM 中定义的 ${revision} 变量。
22.2.3. ${revision} 的定义:在 <properties> 中统一定义 5.5.1
这个 ${revision} 变量的值是在哪里定义的呢?答案就在根 pom.xml 的 <properties> 标签中:
1 | <properties> |
Maven 在解析 POM 时,会使用 <properties> 块中的 <revision>5.5.1</revision>,替换掉 GAV 中的 ${revision} 占位符。
这种“统一定义、多处引用”的机制,实现了当项目需要从 5.5.1 升级到 5.6.0 时,我们 只需要修改根 pom.xml 中 <revision> 标签内的值,整个项目(包含所有子模块)的版本号就会自动、同步更新。
22.2.4. flatten-maven-plugin:让 ${revision} 占位符生效的“魔法”
我们面临一个新问题:${revision} 变量在 Maven 构建时被正确解析了。但是,当我们将项目 install (安装) 到本地仓库或 deploy (部署) 到私服时,其他项目如何“知道”${revision} 究竟代表 5.5.1 呢?
如果 Maven 只是简单地把 pom.xml(包含 ${revision} 变量)部署上去,那么其他项目在依赖 RVP 时,会因为无法解析 ${revision} 变量而失败。
为了解决这个问题,RVP 引入了一个关键插件:flatten-maven-plugin(扁平化插件)。
1 | <!-- 统一版本号管理 --> |
22.2.5. flatten-maven-plugin 工作原理:process-resources 阶段的替换
这个插件的工作原理如下:
<phase>process-resources</phase>:插件被绑定在 Maven 构建生命周期的process-resources阶段(一个较早的阶段)。- “扁平化” (Flatten):当构建执行到此阶段时,
flatten插件会被触发。它会读取原始的pom.xml(包含${revision}变量)。 - “解析” (Resolve):它将 POM 中所有的变量和占位符(如
${revision}、${spring-boot.version})替换为它们在<properties>中定义的 静态值(如5.5.1、3.5.7)。 - “生成新 POM”:该插件会生成一个 新的、“扁平化”的 POM 文件(例如
target目录下的.flattened.pom.xml)。这个新 POM 文件中 不包含任何变量,只有解析后的静态值。 <updatePomFile>true</updatePomFile>:此配置项告诉插件,用这个新生成的“扁平化” POM,去 替换 Maven 后续构建和部署(package,install,deploy)中使用的 POM。
因此,我们最终安装(install)到本地 Maven 仓库或部署(deploy)到私服的 pom.xml,是一个 已经将 ${revision} 解析为 5.5.1 的“干净”版本,从而保证了其他项目的正确依赖。
22.3. 根 pom.xml:dependencyManagement
在 22.2 节中,我们解决了 RVP 5.x 的版本号管理机制。现在,我们进入根 pom.xml 中最庞大、也是最核心的标签:<dependencyManagement>。
22.3.1. [核心] 依赖管理的“两阶段”
在大型多模块项目中,最大的噩梦之一就是“依赖冲突”。例如,ruoyi-demo 模块引入了 hutool-core-5.8.1,而 ruoyi-system 模块引入了 hutool-core-5.8.2,这会导致最终打包时出现版本冲突,引发不可预知的错误。
为了解决这个痛点,Maven 提供了 <dependencyManagement> 标签。它将依赖管理分为了“两阶段”:
- 阶段一:声明
- 位置:在 根
pom.xml的<dependencyManagement>标签内。
* 作用:只声明“如果要用hutool,它的版本 必须 是5.8.40”。
* 效果:不会 为任何模块(包括根模块)实际引入hutool的 jar 包。它只是一个“版本规则”。
- 阶段二:引入 (Dependencies)
- 位置:在 子模块(如
ruoyi-demo)的<dependencies>标签内。
* 作用:实际引入hutool依赖。
* 效果:开发者 只需 提供groupId和artifactId,无需(也不应)提供<version>。Maven 会自动向上查找根 POM 的<dependencyManagement>,并使用那里声明的5.8.40版本。
RVP 5.x 架构正是利用这一机制,在根 pom.xml 中对所有核心技术栈的版本进行了“中央声明”。
22.3.2. RVP 核心技术栈声明
<dependencyManagement> 标签内部声明了 RVP 5.x 所使用的核心技术栈。我们可以将其分为两大类:BOM 导入 和 直接声明。
RVP 5.x 所依赖的核心技术栈及其在框架中的作用如下表所示:
| 技术分类 | 依赖项 (ArtifactId) | 核心价值与在 RVP 中的作用 |
|---|---|---|
| 核心框架 | spring-boot-dependencies | Spring Boot 3。提供整个框架的 IoC、AOP、Web 等基础能力。 |
| 安全框架 | sa-token-spring-boot3-starter | Sa-Token。替代 Spring Security,负责登录认证、权限校验、Token 管理。 |
| 持久层 | mybatis-plus-spring-boot3-starter | MyBatis-Plus。MyBatis 增强工具,提供强大的 CRUD 操作和数据权限等功能。 |
| 多数据源 | dynamic-datasource-spring-boot3-starter | Dynamic-DS。提供动态多数据源切换能力,支持读写分离。 |
| 缓存 | redisson-spring-boot-starter | Redisson。作为 Redis 客户端,提供分布式缓存、分布式锁等服务。 |
| 分布式锁 | lock4j-redisson-spring-boot-starter | Lock4j。基于 Redisson 实现的分布式锁解决方案。 |
| 分布式调度 | snail-job-client-starter | SnailJob。RVP 5.x 引入的分布式任务调度中心(客户端)。 |
| API 文档 | springdoc-openapi-starter-webmvc-api | SpringDoc。替代 Swagger 2,用于自动生成 OpenAPI 3 规范的 API 文档。 |
| 对象映射 | mapstruct-plus-spring-boot-starter | MapStruct-Plus。在编译期自动生成 VO, BO, DTO 之间的转换代码。 |
| 工作流 | warm-flow-mybatis-plus-sb3-starter | Warm-Flow。国产工作流引擎,用于处理业务流程(如审批流)。 |
| 系统监控 | spring-boot-admin-starter-server | Spring Boot Admin。提供 ruoyi-monitor 模块,用于监控应用健康。 |
| 第三方登录 | JustAuth | JustAuth。集成在 ruoyi-common-social 中,用于实现 Gitee 等第三方登录。 |
| 工具包 | hutool-bom | Hutool。Java 工具库,提供日期、字符串、IO 等常用工具方法。 |
22.3.3. 策略一:<scope>import</scope> (BOM 导入)
分析根 pom.xml 的 <dependencyManagement>,我们能看到 RVP 5.x 依赖管理的第一个高级技巧:使用 <scope>import</scope> 来导入 BOM (Bill of Materials)。
1 | <dependencyManagement> |
- BOM (物料清单):BOM 文件本身是一个
pom.xml,它 只包含 一个巨大的<dependencyManagement>列表,用于声明一整套框架(如 Spring Boot)所有组件的版本。 <type>pom</type>和<scope>import</scope>:这两个标签组合使用,告诉 Maven:“请把spring-boot-dependencies这个 POM 文件中所有的<dependencyManagement>声明,原封不动地导入到我(根pom.xml)的<dependencyManagement>中。”
RVP 5.x 通过这个机制,实现了:
- 导入 Spring Boot BOM:RVP 自动继承了 Spring Boot 官方管理的所有依赖版本。
- 导入 Hutool BOM:RVP 自动继承了 Hutool 官方管理的所有工具包版本。
- 导入
ruoyi-common-bom:RVP 导入了 自己 的 BOM,用于管理ruoyi-common-core等所有内部通用模块的版本。我们将在 22.5 节深入解析它。
22.3.4. 策略二:直接声明与 <exclusions> 依赖排除
对于 BOM 未能覆盖的依赖(如 Sa-Token),RVP 5.x 采用了“直接声明”的方式,即在 <dependencyManagement> 中明确指定其 GAV。
1 | <dependencyManagement> |
- 版本引用:所有
<version>标签都引用了 22.1 节中<properties>里定义的变量,如${satoken.version}。 <exclusions>:这是一个主动的“排雷”机制。sa-token-jwt默认会依赖一个hutool-all包,而 RVP 5.x 提倡的是按需引入hutool的子模块(如hutool-core)。为了避免hutool-all带来的潜在冲突和臃肿,RVP 在声明sa-token-jwt时,通过<exclusions>标签 主动排除了 它对hutool-all的依赖。
22.4. 根 pom.xml 构建配置 (<build>)
在 22.3 节中,我们解析了 <dependencyManagement> 如何“声明”依赖。现在,我们转向根 pom.xml 的 <build> 标签。此标签定义了项目如何被编译、测试、以及如何处理资源文件。这些配置同样会被所有子模块继承。
22.4.1. maven-compiler-plugin:指定 Java 17 编译
build 块中的第一个核心插件是 maven-compiler-plugin,它负责将 .java 源码编译为 .class 字节码。
1 | <plugin> |
<source>${java.version}</source>:指定了源码的 JDK 版本。${java.version}变量在<properties>中被定义为17。<target>${java.version}</target>:指定了编译后.class文件应兼容的 JVM 版本,同样是17。<encoding>${project.build.sourceEncoding}</encoding>:指定了编译时使用UTF-8编码,防止中文乱码。
22.4.2. annotationProcessorPaths:Lombok 与 MapStruct-Plus 的编译期处理
在 maven-compiler-plugin 配置内部,有一个至关重要的 <annotationProcessorPaths> (注解处理器路径) 标签。
RVP 框架大量使用了“编译期注解”。这些注解(如 Lombok 的 @Data)不是在“运行”时生效,而是在“编译”时触发 Java 代码的自动生成。
1 | <configuration> |
此配置块告诉 maven-compiler-plugin:在编译时,请加载并运行以下处理器:
- Lombok:用于自动生成
getter/setter、构造函数等。 - Spring Boot:用于处理
@ConfigurationProperties,生成spring-configuration-metadata.json文件(为 YML 提供智能提示)。 - MapStruct-Plus:用于自动生成 VO, DTO, BO 之间的映射转换实现类。
- lombok-mapstruct-binding:一个“粘合剂”插件,确保 Lombok 生成的方法能被 MapStruct-Plus 正确识别。
22.4.3. <compilerArgs>-parameters</compilerArgs>:为反射保留参数名
1 | <configuration> |
默认情况下,Java 编译后的 .class 文件会擦除方法的参数名(例如 findUser(String userName) 会变为 findUser(String arg0))。
痛点:这导致了 Spring MVC, MyBatis 等依赖“反射”的框架,无法通过参数名自动绑定值,开发者必须手动添加 @Param("userName") 这样的注解,非常繁琐。
解决方案:<arg>-parameters</arg> 告诉编译器(javac):“请在 .class 文件中保留方法的参数名”。这使得 RVP 中的 Spring 和 MyBatis 代码可以大量减少 @Param 或 @RequestParam 的使用,让代码更简洁。
22.4.4. resources 插件:application.yml 变量替换
<resources> 标签用于控制 src/main/resources 目录下的文件如何被处理。RVP 5.x 采用了一种“两段式”的资源处理策略。
1 | <resources> |
- 第一段 (filtering: false):首先,Maven 复制
src/main/resources下的 所有 文件,并且 关闭过滤(filtering: false)。这是为了保证二进制文件(如ip2region.xdb数据库)在复制过程中不会因“变量替换”而被损坏。 - 第二段 (filtering: true):接着,Maven 再次 处理
src/main/resources目录,但这次:includes:只包含application*、bootstrap*、banner*这几类文件。filtering: true:开启过滤。
最终效果:在 application.yml 中,我们可以使用 Maven 变量 @profiles.active@(注意是 @ 符号,而非 $)。当 dev profile 激活时,filtering: true 会将 application.yml 中的 @profiles.active@ 替换为 静态字符串 dev,从而激活 Spring Boot 的 dev 环境。
22.4.5. repositories:配置华为云 Maven 仓库
pom.xml 文件末尾的 <repositories> 和 <pluginRepositories> 标签,用于指定 Maven 下载依赖的远程仓库地址。
1 | <repositories> |
动机:Maven 默认的中央仓库(Repo1)在国外,国内访问速度较慢。
方案:RVP 5.x 默认配置了华为云的 Maven 镜像仓库(mirrors.huaweicloud.com),用于下载所有依赖(repositories)和 Maven 插件(pluginRepositories),这极大地 加快了 国内用户的依赖下载和项目构建速度。
22.5. [核心] ruoyi-common-bom 详解
22.5.1. BOM (Bill of Materials) 设计模式解析
在 Maven 中,BOM (Bill of Materials) 即“物料清单”,是一种专门用于依赖版本管理的 pom.xml 文件。
它的核心设计哲学是:
- 它不被继承:BOM 文件不作为其他模块的
<parent>。 - 它只被导入:它的唯一目的是在根 POM 的
<dependencyManagement>中被<scope>import</scope>导入。 - 它的职责单一:BOM 文件本身几乎只包含一个
<dependencyManagement>块,这个块的作用就是“声明”一整套相互兼容的依赖版本。
RVP 5.x 架构就是利用此模式,将所有 ruoyi-common-* 插件化模块的版本,集中到 ruoyi-common-bom 中进行统一声明。
22.5.2. ruoyi-common-bom/pom.xml 源码解析:它“管理”了哪些版本?
我们来分析``RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-bom/pom.xml` 中的源码:
1 | <project ...> |
关键点分析:
<packaging>pom</packaging>:它本身是一个 POM,不产生jar包。<dependencyManagement>:这是它的 唯一 核心内容。- 声明内容:它声明了 RVP 框架所有“通用功能插件”(如
-core,-doc,-excel,-log,-redis,-mybatis,-satoken,-web等)的版本。 - 版本统一:所有这些插件模块的版本,全部统一为
${revision}。
RVP 5.x 架构的依赖传递链:子模块 (ruoyi-demo) -> 根 POM (ruoyi-vue-plus) -> BOM (ruoyi-common-bom)
当 ruoyi-demo 模块需要使用 redis 功能时,它只需引入:
1 | <dependency> |
Maven 会自动向上(根 POM)查找版本 -> 根 POM 通过 <scope>import</scope> 指向 ruoyi-common-bom -> ruoyi-common-bom 声明了 ruoyi-common-redis 的版本是 ${revision} -> ${revision} 被解析为 5.5.1。
22.5.3. [重点] 为什么 bom 文件没有 <parent>?
我们注意到 ruoyi-common-bom/pom.xml 中 没有 <parent> 标签,它不继承自 ruoyi-vue-plus 根 POM。
这是一个至关重要的解耦设计。
- 痛点:如果
ruoyi-common-bom继承了根 POM (<parent>ruoyi-vue-plus</parent>),那么任何想使用 RVP 通用模块(如ruoyi-common-redis)的 外部项目,在导入此 BOM 时,都会被迫同时继承ruoyi-vue-plus的所有配置。这造成了不必要的强耦合。 - RVP 5.x 方案:通过移除
<parent>,ruoyi-common-bom变成了一个“独立、自包含”的物料清单。任何 Maven 项目(无论是不是 RVP 项目)都可以安全地<scope>import</scope>这个 BOM,来获取 RVPcommon模块的官方版本,而不会污染自己的父 POM 继承链。
随之而来的问题:既然 ruoyi-common-bom 没有父 POM,它如何知道 ${revision} 变量的值(5.5.1)呢?
答案在 bom 文件的 <properties> 标签中:
1 | <properties> |
ruoyi-common-bom 必须 在自己的 pom.xml 中 重新定义 一次 <revision> 变量。这是为了确保它在“独立”的情况下,也能正确解析其 <dependencyManagement> 中所有模块的版本号。
22.5.4. ruoyi-common/pom.xml 的职责:聚合所有 common 插件
现在我们再来看 RuoYi-Vue-Plus/ruoyi-common/pom.xml 文件。它的作用又是什么?
1 | <parent> |
ruoyi-common 模块的职责是“组织聚合”。它同样是一个 <packaging>pom</packaging> 模块,它不管理版本(那是 bom 的事),它只负责在 <modules> 标签中,将 所有 ruoyi-common-* 插件(包括 -bom 自己)聚合在一起。
最终结构:
- 根
pom.xml:通过<module>ruoyi-common</module>聚合common目录。 ruoyi-common/pom.xml:通过<module>ruoyi-common-core</module>等标签,聚合所有插件子模块。ruoyi-common-bom/pom.xml:通过<dependencyManagement>,声明 所有插件子模块的 版本。
这种设计实现了“组织结构”与“版本声明”的彻底分离。
22.6. ruoyi-modules 与 ruoyi-demo 依赖分析
在 22.5 节中,我们解析了 ruoyi-common 模块如何通过 bom 文件来声明“通用插件”的版本。现在,我们进入“业务层”——ruoyi-modules 目录,分析业务模块(特别是 ruoyi-demo)是如何“消费”这些通用插件的。
22.6.1. ruoyi-modules/pom.xml:业务模块的“聚合器”
我们首先分析 RuoYi-Vue-Plus/ruoyi-modules/pom.xml。
1 | <parent> |
<parent>:它继承自根pom.xml(ruoyi-vue-plus),因此它能“感知”到根 POM 中定义的所有<properties>和<dependencyManagement>规则。<packaging>pom</packaging>:它的身份同样是“父项目”。<modules>:它的职责非常单一,就是作为“业务模块的聚合器”,将ruoyi-demo(演示)、ruoyi-generator(代码生成)、ruoyi-job(调度任务)、ruoyi-system(系统核心)这四个业务模块组织在一起。
22.6.2. ruoyi-demo/pom.xml 依赖分析:按需引入 common 插件
ruoyi-demo 模块是 RVP 5.x 中用于“二次开发”的示例模块。分析它的 pom.xml,是理解 RVP 依赖管理“最佳实践”的关键。
1 | <parent> |
22.6.3. [重点] ruoyi-demo 如何实现“无需声明版本”?
我们注意到 ruoyi-demo 的 <dependencies> 块中,所有 ruoyi-common-* 依赖 都没有声明 <version> 标签。这就是 RVP 5.x 架构“优雅”的体现。
其背后的依赖解析链条如下:
ruoyi-demo在<dependencies>中请求ruoyi-common-redis(无版本)。- Maven 沿着
demo的<parent>找到ruoyi-modules(pom.xml)。 ruoyi-modules没有声明版本,Maven 继续沿着它的<parent>找到 根pom.xml(ruoyi-vue-plus)。- 根
pom.xml的<dependencyManagement>块中,导入(<scope>import</scope>)了ruoyi-common-bom。 - Maven 在
ruoyi-common-bom的<dependencyManagement>块中,找到了ruoyi-common-redis的版本声明:<version>${revision}</version>。 - Maven 解析根
pom.xml的<properties>,将${revision}替换为5.5.1。 - 最终:
ruoyi-demo成功引入了ruoyi-common-redis:5.5.1。
这种设计使得 ruoyi-demo(以及所有业务模块)在开发时,可以像“点餐”一样,按需引入 ruoyi-common-* 插件,而 完全不需要关心 这些插件的版本号,版本由根 POM 和 BOM 统一控制。
22.6.4. [实战] 二次开发:引入新依赖的最佳实践
在 RVP 基础上进行二次开发时,我们必然需要引入新的依赖。根据 RVP 5.x 的架构哲学,引入新依赖有严格的最佳实践。
场景一:引入 RVP common 模块(例如 demo 模块需要发邮件)
如果 ruoyi-demo 需要使用邮件功能,我们只需引入 ruoyi-common-mail 即可。
操作:
- 打开
ruoyi-demo/pom.xml文件。 - 在
<dependencies>块中,添加以下代码:
1 | <dependency> |
[最佳实践]:严禁 添加 <version> 标签。ruoyi-common-bom 已经统一管理了所有 common 模块的版本。
场景二:引入全新第三方依赖(例如 commons-lang3)
假设 ruoyi-demo 需要引入 org.apache.commons:commons-lang3 这个 RVP 默认未包含的依赖。
错误实践:直接在 ruoyi-demo/pom.xml 中添加 <dependency> 并硬编码 <version>3.12.0</version>。
后果:这破坏了 RVP 的集中管理原则。如果 ruoyi-system 也引入了 3.13.0 版本的 commons-lang3,就会立刻产生版本冲突。
[最佳实践] 遵循 RVP 的“两阶段”模式:
步骤一:在根 pom.xml 中“声明”版本
- 打开 根
pom.xml(RuoYi-Vue-Plus/pom.xml)。 - 在
<properties>标签中,添加一个新的版本变量:1
2
3<properties>
<commons-lang3.version>3.12.0</commons-lang3.version>
</properties> - 在
<dependencyManagement>-><dependencies>标签中,添加依赖声明:1
2
3
4
5<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
步骤二:在 ruoyi-demo/pom.xml 中“引入”依赖
- 打开
ruoyi-demo/pom.xml。 - 在
<dependencies>块中,不带版本号 地引入:1
2
3
4<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
结论:在二次开发中,所有新依赖(无论是 RVP 内部的还是第三方的),都应遵循“版本声明在根 POM (dependencyManagement),按需引入在子模块 (dependencies)”的黄金法则。
22.7. ruoyi-admin:唯一的“可执行”聚合器
我们现在分析 ruoyi-admin/pom.xml。这个模块是 RVP 5.x 架构的“主入口”,是最终运行的主服务。
22.6.1. ruoyi-admin/pom.xml 依赖解析:聚合所有 common 和 modules
ruoyi-admin 的 pom.xml 同样继承自根 POM,但它的职责不是声明,而是“实际引入”。
1 | <parent> |
<packaging>jar</packaging>:它的身份标识是jar,意味着它将被打包成一个jar文件。<dependencies>:它像一个“总装车间”,将ruoyi-common-*(通用插件)和ruoyi-modules-*(业务模块)实际引入 到项目中。- 版本管理:同样,所有依赖都 无需声明
<version>,版本全部由根 POM 的<dependencyManagement>和ruoyi-common-bom统一控制。
22.7.2. [核心] spring-boot-maven-plugin:可执行“Fat Jar”的构建者
ruoyi-admin/pom.xml 中最关键的配置在 <build> 标签内。
1 | <build> |
spring-boot-maven-plugin 是 Spring Boot 官方提供的打包插件。它的存在,是 ruoyi-admin 能够被独立运行的关键。
22.7.3. [重点] 编译 (compile) vs 打包 (repackage) 的本质区别
1Maven 的标准 package(编译)和 Spring Boot 的 repackage(重新打包)会产生两种截然不同的 jar 包。
标准
package(编译产物):- 执行 Maven 的
package命令,会先触发compile编译。 - 此时
maven-jar-plugin会创建一个jar包(在target目录中通常叫ruoyi-admin.jar.original)。 - 这个
jar包 只包含ruoyi-admin模块自己的.class文件和resources。 - 它不包含
ruoyi-common-redis、sa-token、spring-boot等任何第三方依赖的jar包。 - 结论:这个
original包体积很小(几 MB),无法通过java -jar独立运行,因为它缺少依赖。
- 执行 Maven 的
repackage(Spring Boot 打包):spring-boot-maven-plugin插件的<goal>repackage</goal>会在标准package之后 执行。- 它会拿
original包作为基础,然后将 所有 在<dependencies>中引入的依赖(如ruoyi-common-redis.jar,sa-token.jar等)全部解压并重新打包 进最终的jar包中。
22.6.4. repackage 如何将 lib 和 classes 打包?
repackage 插件会生成一个可执行的“Fat Jar”(在 target 目录中叫 ruoyi-admin.jar),其内部结构通常如下:
BOOT-INF/classes/:存放ruoyi-admin模块自身的业务代码.class文件。BOOT-INF/lib/:[核心] 存放所有第三方依赖的jar包(如sa-token.jar)。org/springframework/boot/loader/:存放 Spring Boot 的“启动加载器”,java -jar命令真正执行的是这个加载器,它知道如何去加载BOOT-INF目录下的类和lib。
结论:ruoyi-admin 通过聚合所有业务模块,并使用 spring-boot-maven-plugin,最终将自己打包成一个包含所有依赖、可独立运行的“Fat Jar”。
22.8. ruoyi-extend:独立运行的“卫星服务”
现在我们分析 ruoyi 的拓展模块 RuoYi-Vue-Plus/ruoyi-extend/pom.xml。
22.7.1. ruoyi-extend/pom.xml 源码解析
1 | <parent> |
与 ruoyi-modules 一样,ruoyi-extend 也是一个 <packaging>pom</packaging> 的聚合器:
- 它继承自根 POM (
ruoyi-vue-plus),获取依赖管理能力。 - 它聚合了
ruoyi-monitor-admin(监控中心)和ruoyi-snailjob-server(调度中心)两个模块。
22.7.2. extend 与 modules 的本质区别
ruoyi-modules(业务模块)和 ruoyi-extend(扩展模块)虽然都是聚合器,但它们的 设计目标 截然不同:
ruoyi-modules(如ruoyi-system):聚合的是 业务库 (Library)。它们自身不能运行,必须被ruoyi-admin引入 并打包后,才能作为admin服务的一部分运行。ruoyi-extend(如ruoyi-monitor-admin):聚合的是 独立服务 (Application)。它们 不被ruoyi-admin引入。相反,它们和ruoyi-admin是“兄弟”关系,都是可以独立运行的 Spring Boot 应用。
22.7.3. ruoyi-snailjob-server/pom.xml 源码解析
ruoyi-snailjob-server 是 SnailJob 的调度服务端。分析其 pom.xml:
1 | <parent> |
关键点分析:
<packaging>jar</packaging>:它也是一个jar包项目。snail-job-server-starter:它引入了 SnailJob 的 服务端 依赖。spring-boot-maven-plugin:它 同样 在<build>块中配置了repackage目标,证实了它也会被打包成一个可独立运行的“Fat Jar”。
22.7.4. 总结:RVP 5.x 的三个可执行服务
通过对 ruoyi-admin、ruoyi-monitor-admin 和 ruoyi-snailjob-server 三个模块 pom.xml 文件的推断,我们得出结论:
RVP 5.x 架构在 Maven 层面定义了三个 可独立执行的服务。它们都在各自的 <build> 插件中配置了 spring-boot-maven-plugin,用于生成可运行的“Fat Jar”。
| 模块 | 是否可打包 | 最终产物 (Fat Jar) | 职责 |
|---|---|---|---|
ruoyi-admin | 是 | ruoyi-admin.jar | RVP 主业务服务 |
ruoyi-monitor-admin | 是 | ruoyi-monitor-admin.jar | Spring Boot Admin 监控服务端 |
ruoyi-snailjob-server | 是 | ruoyi-snailjob-server.jar | SnailJob 任务调度服务端 |
ruoyi-system | 否 | (无,被 admin 聚合) | 业务库 (Library) |
ruoyi-common-redis | 否 | (无,被 admin 聚合) | 通用插件库 (Library) |
这就是 RVP 5.x 架构下,我们为什么需要启动三个 Java 服务(admin, monitor, snailjob)的 Maven 根本原因。









