Gradle 多项目构建:根项目与子项目配置、跨项目依赖
当项目规模变大时,多模块构建是必然选择。
多项目结构
my-company/
├── build.gradle # 根项目构建脚本
├── settings.gradle # 项目定义
├── gradle.properties # 全局属性
├── app/ # 应用模块
│ └── build.gradle
├── module-user/ # 用户模块
│ └── build.gradle
├── module-order/ # 订单模块
│ └── build.gradle
└── module-common/ # 公共模块
└── build.gradlesettings.gradle——定义项目结构
groovy
// settings.gradle
rootProject.name = 'my-company'
// 包含子项目
include 'app', 'module-user', 'module-order', 'module-common'
// 为子项目指定目录名(可选)
include('module-payment')
project(':module-payment').projectDir = file('modules/payment')根项目的 build.gradle
根项目通常不打包代码,而是负责:
- 统一插件版本
- 统一依赖版本
- 配置公共行为
groovy
// 根项目 build.gradle
// 所有子项目默认插件
subprojects {
apply plugin: 'java-library'
apply plugin: 'idea'
// 统一配置仓库
repositories {
mavenCentral()
maven { url 'https://maven.aliyun.com/repository/public' }
}
// 统一 Java 版本
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
// 统一依赖管理
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'
}
// 统一测试配置
test {
useJUnitPlatform()
maxParallelForks = 4
}
}
// 为特定子项目添加额外配置
project(':app') {
apply plugin: 'org.springframework.boot'
dependencies {
implementation project(':module-common')
implementation project(':module-user')
implementation project(':module-order')
}
}子项目的 build.gradle
module-common
groovy
// 不需要写 version,由 BOM 或父项目统一管理
plugins {
id 'java-library'
id 'io.spring.dependency-management'
}
dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.2.0'
}
}
dependencies {
// API 表示传递依赖
api 'org.apache.commons:commons-lang3:3.12.0'
api 'com.google.guava:guava:32.1.3-jre'
// Implementation 表示不传递
implementation 'com.alibaba:fastjson:2.0.0'
}module-user
groovy
plugins {
id 'java-library'
id 'io.spring.dependency-management'
}
dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.2.0'
}
}
dependencies {
implementation project(':module-common')
api 'org.springframework:spring-context:6.1.0'
implementation 'org.springframework.boot:spring-boot-starter-web'
}app(应用模块)
groovy
plugins {
id 'org.springframework.boot'
id 'io.spring.dependency-management'
}
dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.2.0'
}
}
bootJar {
// Spring Boot JAR 配置
archiveFileName = "${project.name}.jar"
}
dependencies {
implementation project(':module-common')
implementation project(':module-user')
implementation project(':module-order')
}跨项目依赖
依赖另一个子项目
groovy
dependencies {
// 依赖 module-common
implementation project(':module-common')
// 依赖多个子项目
implementation project(':module-user')
implementation project(':module-order')
}有条件地依赖
groovy
// 只有当某个子项目存在时才依赖
subprojects {
afterEvaluate {
if (project.hasProperty('featureX')) {
dependencies {
implementation project(':feature-x')
}
}
}
}跨项目任务执行
在根项目执行子项目任务
bash
# 所有子项目执行 build
./gradlew build
# 所有子项目执行 test
./gradlew test
# 只构建特定子项目及其依赖
./gradlew :app:build -x :module-user:test
# 只构建特定子项目(不构建依赖)
./gradlew :module-common:build --no-build-dependents任务执行顺序
Gradle 自动根据项目间的依赖关系计算执行顺序:
app 依赖 module-user, module-order, module-common
module-user 依赖 module-common
module-order 依赖 module-common
module-common 无依赖
执行顺序:
module-common → module-user → module-order → app并行执行子项目
bash
./gradlew build --parallel配置继承与覆盖
子项目覆盖父项目的配置
groovy
// 根项目 subprojects 中定义
subprojects {
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
}
// app 子项目覆盖
project(':app') {
tasks.withType(JavaCompile) {
options.encoding = 'GBK' // 覆盖为 GBK
}
}条件化配置
groovy
subprojects {
// 只有 Java 插件应用时才配置
plugins.withId('java') {
repositories {
mavenCentral()
}
}
// 只有 web 相关模块才配置
if (project.name.contains('web') || project.name.contains('rest')) {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
}
}
}多环境配置
profiles 在 Gradle 中的实现
Gradle 用Source Set或Product Flavor替代 Maven Profile:
groovy
// 使用 Source Set 实现多环境
sourceSets {
dev {
java.srcDirs = ['src/dev/java']
}
prod {
java.srcDirs = ['src/prod/java']
}
}
// 或使用 Product Flavor
flavorDimensions += "environment"
productFlavors {
dev {
dimension "environment"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
}
prod {
dimension "environment"
}
}环境变量配置
groovy
subprojects {
tasks.withType(JavaExec) {
environment 'APP_ENV', project.findProperty('env') ?: 'dev'
}
}项目聚合任务
groovy
// 根项目 build.gradle
// 所有子项目执行 assemble
tasks.register('deployAll') {
group = 'build'
description = '部署所有应用'
dependsOn gradle.includedBuilds*.task(':deploy')
}
// 收集所有子项目的 JAR
task collectJars {
group = 'build'
doLast {
subprojects.each { proj ->
proj.tasks.assemble.outputs.files.each { file ->
if (file.name.endsWith('.jar')) {
copy {
from file
into "${rootDir}/output/jars"
}
}
}
}
}
}面试高频问题
问:Gradle 多项目构建和 Maven 多模块有什么本质区别?
答:Maven 多模块用父子继承关系管理,parent POM 定义公共配置,子 POM 继承。Gradle 多项目用聚合管理,所有项目平铺在根项目下,通过 settings.gradle 的 include 声明。Gradle 的方式更灵活——根项目可以有自己的代码(Maven 的父 POM 通常不行),子项目之间的依赖表达也更自然(project(':module-a') 语法比 Maven 的 GAV 坐标引用更直接)。
问:subprojects 和 allprojects 有什么区别?
答:subprojects 只匹配直接子项目,allprojects 匹配根项目 + 所有子项目。常见用法是 subprojects 用来配置子项目的共同行为,allprojects 用来配置仓库等根项目也需要的内容。
