1. 多模块项目结构:settings.gradle 配置、根项目与子项目、include 与项目路径
1.1 为什么需要多模块结构
单体项目随着业务增长会逐渐膨胀,编译时间、代码耦合度、团队协作效率都会急剧下降。多模块结构将工程按业务边界或技术层拆分为独立子项目,每个子项目拥有独立构建脚本,根项目只负责编排和聚合。Gradle 通过 settings.gradle 文件定义模块拓扑,这是多模块构建的唯一入口。
核心原则:Gradle 多模块的模块关系由 settings.gradle 静态声明,运行时不可变。所有子模块的发现、路径解析、任务依赖重组都基于该文件的声明顺序与路径规则。
1.2 根项目与子项目:两种角色
| 角色 | 位置 | 构建脚本 | 职责 |
|---|---|---|---|
| 根项目 | 项目最顶层目录 | build.gradle / build.gradle.kts | 全局配置、插件声明、子项目公共逻辑 |
| 子项目 | 根目录下的子目录 | 各子目录内的 build.gradle | 业务模块 / 基础库 / 独立组件 |
根项目本身也可以包含源代码(不推荐),多数场景只作为聚合容器。子项目在 settings.gradle 中通过 include 声明后被自动识别,并继承根项目的 allprojects 或 subprojects 配置块。
1.3 settings.gradle 的核心作用
settings.gradle 位于项目根目录,Gradle 启动时第一个读取的就是它。其核心职责包括:
- 声明项目名称(
rootProject.name) - 注册子模块(
include语句) - 定义项目路径与物理目录的映射
- 配置模块间的依赖查找策略
- 引入复合构建或插件管理
关键顺序:settings.gradle 执行完毕后,Gradle 才会解析各子项目的 build.gradle。settings 中声明的路径直接影响任务调度时的项目引用名。
// settings.gradle — 最小化多模块配置示例
rootProject.name = "my-platform"
include "core"
include "service:user-service"
include "service:order-service"
include "web:admin-console"
1.4 include 与项目路径语法
include 接受一个或多个字符串参数,每个字符串代表一个逻辑项目路径。路径中的冒号 : 是 Gradle 的路径分隔符,对应文件系统的子目录层级。下表列出常见模式:
| include 写法 | 实际目录结构(相对于根) | 项目引用名 |
|---|---|---|
include "core" | ./core/ | :core |
include "service:user-service" | ./service/user-service/ | :service:user-service |
include "web:admin-console" | ./web/admin-console/ | :web:admin-console |
include "libs:security" | ./libs/security/ | :libs:security |
项目引用名(:core、:service:user-service)在跨模块依赖声明、任务名称引用、Gradle 命令行中统一使用。
// 在 build.gradle 中引用子项目的路径
dependencies {
implementation project(":core")
implementation project(":service:user-service")
testImplementation project(":libs:security")
}
避免踩坑:
include 路径中的冒号前后不要加空格。include "service : user-service" 会触发项目路径解析异常。路径必须与文件系统目录名严格一致(大小写敏感,Linux/macOS 尤其注意)。
1.5 多模块项目结构图
下图展示了一个典型多模块 Gradle 项目的物理目录与逻辑项目路径的对应关系。根项目作为聚合根,子项目按业务域分层组织。
1.6 命令行验证模块结构
配置完成后,通过 Gradle 内置任务可以快速验证模块是否被正确识别:
# 列出所有项目(含根项目)
gradle projects
# 输出示例:
# Root project 'my-platform'
# +--- Project ':core'
# +--- Project ':service'
# +--- Project ':service:user-service'
# +--- Project ':service:order-service'
# +--- Project ':web'
# +--- Project ':web:admin-console'
# 查看特定子项目的属性
gradle :core:properties
调试技巧:如果某子项目没有出现在
gradle projects 列表中,优先检查 settings.gradle 中的 include 路径是否与目录名完全匹配。Windows 系统注意大小写与反斜杠问题,统一使用正斜杠 / 或冒号路径。
1.7 常见错误与解决方案
| 错误现象 | 根本原因 | 修复方法 |
|---|---|---|
| Project with path ':xxx' not found | include 路径与目录不一致或遗漏声明 | 检查 settings.gradle 并补全 include "xxx" |
| Settings file 'settings.gradle' not found | 根目录缺少 settings.gradle | 在项目根目录创建 settings.gradle |
| Cannot evaluate root project before settings loaded | 在 settings.gradle 中引用了项目对象 | settings 阶段只做声明,不要调用 project API |
| Duplicate project path | 两次 include 了相同路径 | 移除重复的 include 声明 |
1.8 性能优化:合理控制模块粒度
多模块并非越多越好。每个子项目都会增加配置阶段的开销。推荐原则:
- 按变更边界拆分:一个模块对应一个独立交付单元或业务域
- 避免过度嵌套:层级深度控制在 2~3 层,过深会增加路径解析成本
- 利用
includeFlat快速集成同级模块(适用于扁平结构) - 启用配置缓存:在 gradle.properties 中设置
org.gradle.configuration-cache=true
// gradle.properties — 开启配置缓存与并行执行
org.gradle.parallel=true
org.gradle.configuration-cache=true
org.gradle.caching=true
本章小结:settings.gradle 是多模块项目的神经中枢。正确理解根项目 / 子项目角色、掌握 include 路径语法、熟练使用
gradle projects 验证,是后续章节学习任务调度与跨模块依赖管理的基础。下一章将深入 allprojects 与 subprojects 配置块,实现统一插件管理与版本控制。