📌 第一阶段:Gradle 基础概念与环境搭建 🎯 1. Gradle 是什么?深度解析 1.1 Gradle 的核心优势 Gradle是一个开源的构建自动化工具,专注于灵活性和性能。它结合了Ant的强大功能和Maven的依赖管理概念。
🔧 五大核心优势:
高性能 :增量构建、构建缓存、并行执行
灵活性 :基于Groovy/Kotlin DSL的强大脚本能力
可扩展性 :丰富的插件生态系统
多语言支持 :Java、Kotlin、Scala、C++、Python等
企业级特性 :构建扫描、依赖洞察、性能分析
1.2 Gradle vs. Maven vs. Ant 详细对比
特性
Gradle
Maven
Ant
配置语言
Groovy/Kotlin DSL
XML
XML
构建性能
🥇 最快(增量构建+缓存)
🥉 较慢
🥈 中等
灵活性
🥇 极高(编程式配置)
🥉 较低(约定优于配置)
🥈 高(过程式)
学习曲线
🥈 中等偏陡
🥇 相对简单
🥉 复杂
依赖管理
🥇 强大且灵活
🥈 强大但固化
🥉 需手动管理
多项目支持
🥇 原生支持
🥈 通过聚合
🥉 需手动配置
IDE支持
🥇 优秀
🥇 优秀
🥈 一般
生态系统
🥈 快速发展
🥇 最成熟
🥉 逐渐衰落
企业采用
🥈 快速增长
🥇 最广泛
🥉 逐渐减少
1.3 Gradle 的核心概念 🎯 项目(Project)
每个构建都包含一个或多个项目
项目代表可以构建的组件(如JAR库、Web应用等)
由build.gradle文件定义
🎯 任务(Task)
构建的基本工作单元
如编译代码、运行测试、创建JAR等
任务之间可以有依赖关系
🎯 插件(Plugin)
扩展Gradle功能的模块
提供任务、约定和配置
如Java插件、Spring Boot插件等
🎯 构建脚本(Build Script)
使用Groovy或Kotlin DSL编写
定义项目配置、依赖、任务等
具有强大的编程能力
🛠️ 2. Gradle 安装与配置详解 2.1 安装方式对比 方式1:使用Gradle Wrapper(推荐)
1 2 3 4 5 6 7 8 ./gradlew build gradlew.bat build
方式2:手动安装
1 2 3 4 5 6 7 8 9 10 export GRADLE_HOME=/opt/gradle/gradle-8.4export PATH=$PATH :$GRADLE_HOME /bingradle --version
方式3:包管理器安装
1 2 3 4 5 6 7 8 9 10 11 brew install gradle sudo apt install gradle choco install gradle scoop install gradle
2.2 Gradle Wrapper 详解 🔧 生成Wrapper
1 2 3 4 5 6 7 8 9 10 11 12 gradle wrapper --gradle-version 8.4 project/ ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── build.gradle
📝 gradle-wrapper.properties配置
1 2 3 4 5 6 7 distributionBase =GRADLE_USER_HOME distributionPath =wrapper/dists distributionUrl =https\://services.gradle.org/distributions/gradle-8.4-bin.zip networkTimeout =10000 zipStoreBase =GRADLE_USER_HOME zipStorePath =wrapper/dists
🚀 Wrapper优化配置
1 2 3 4 5 6 7 8 9 10 11 distributionUrl =https\://mirrors.cloud.tencent.com/gradle/gradle-8.4-bin.zip distributionUrl =https\://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.4-bin.zip networkTimeout =10000 # 网络超时时间(毫秒) validateDistributionUrl =true # 验证下载URL zipStoreBase =GRADLE_USER_HOME # ZIP存储基础目录 zipStorePath =wrapper/dists # ZIP存储路径
💡 Wrapper配置实战案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 distributionUrl=https\://nexus.company.com/repository/gradle-distributions/gradle-8.4-bin.zip ./gradlew wrapper --gradle-version 8.4 --distribution-type bin distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists
2.3 Gradle 配置优化 📁 gradle.properties(项目级配置)详解
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 org.gradle.daemon =true org.gradle.parallel =true org.gradle.configureondemand =true org.gradle.caching =true org.gradle.jvmargs =-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 systemProp.file.encoding =UTF-8 systemProp.http.proxyHost =proxy.company.com systemProp.http.proxyPort =8080 systemProp.http.proxyUser =username systemProp.http.proxyPassword =password systemProp.https.proxyHost =proxy.company.com systemProp.https.proxyPort =8080 systemProp.https.proxyUser =username systemProp.https.proxyPassword =password systemProp.http.nonProxyHosts =localhost|127.0.0.1|*.company.com org.gradle.console =rich org.gradle.logging.level =lifecycle org.gradle.warning.mode =all version =1.0.0-SNAPSHOT app.name =MyApplication app.description =My Gradle Application app.mainClass =com.example.Application db.url =jdbc:mysql://localhost:3306/myapp db.username =dev_user db.password =dev_password build.timestamp =${new Date().format('yyyy-MM-dd HH:mm:ss')}
🏠 ~/.gradle/gradle.properties(全局配置)详解
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 32 33 34 35 36 37 38 39 40 41 42 43 org.gradle.jvmargs =-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC org.gradle.parallel =true org.gradle.caching =true org.gradle.daemon =true systemProp.http.proxyHost =proxy.company.com systemProp.http.proxyPort =8080 systemProp.https.proxyHost =proxy.company.com systemProp.https.proxyPort =8080 systemProp.gradle.wrapperUser =username systemProp.gradle.wrapperPassword =password nexusUsername =your_username nexusPassword =your_password signing.keyId =12345678 signing.password =your_signing_password signing.secretKeyRingFile =/Users/username/.gnupg/secring.gpg developer.name =John Doe developer.email =john.doe@company.com developer.organization =My Company org.gradle.console =rich org.gradle.warning.mode =all
💡 全局配置实战案例
案例1:企业开发环境统一配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 org.gradle.jvmargs =-Xmx6g -XX:MaxMetaspaceSize=512m -XX:+UseG1GC systemProp.http.proxyHost =proxy.company.com systemProp.http.proxyPort =8080 systemProp.https.proxyHost =proxy.company.com systemProp.https.proxyPort =8080 systemProp.http.nonProxyHosts =*.company.com|localhost nexusUsername =${env.NEXUS_USERNAME} nexusPassword =${env.NEXUS_PASSWORD} developer.name =${env.USER} developer.email =${env.USER}@company.com
案例2:个人开发机优化配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 org.gradle.jvmargs =-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC -XX:+UseStringDeduplication org.gradle.parallel =true org.gradle.workers.max =8 org.gradle.caching =true org.gradle.configuration-cache =true org.gradle.console =verbose org.gradle.logging.level =info
案例3:CI/CD环境配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 org.gradle.jvmargs =-Xmx4g -XX:MaxMetaspaceSize=512m org.gradle.daemon =false # CI环境不使用守护进程 org.gradle.parallel =true # 启用并行构建 org.gradle.caching =true # 启用构建缓存 org.gradle.console =plain # 纯文本输出 org.gradle.logging.level =info # 详细日志 org.gradle.warning.mode =fail # 警告时失败
📁 3. Gradle 项目结构深度解析 3.1 标准项目结构 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 my-gradle-project/ ├── build.gradle(.kts) ├── settings.gradle(.kts) ├── gradle.properties ├── gradlew ├── gradlew.bat ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src/ │ ├── main/ │ │ ├── java/ │ │ ├── kotlin/ │ │ ├── resources/ │ │ └── webapp/ │ ├── test / │ │ ├── java/ │ │ ├── kotlin/ │ │ └── resources/ │ └── integrationTest/ ├── build/ │ ├── classes/ │ ├── libs/ │ ├── reports/ │ └── tmp/ └── README.md
3.2 核心文件详解 📋 build.gradle 基础结构
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 32 33 plugins { id 'java' id 'application' id 'org.springframework.boot' version '2.7.0' } group = 'com.example' version = '1.0.0' sourceCompatibility = '11' repositories { mavenCentral() gradlePluginPortal() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.junit.jupiter:junit-jupiter' } tasks.named('test' ) { useJUnitPlatform() } application { mainClass = 'com.example.Application' }
⚙️ settings.gradle 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 rootProject.name = 'my-gradle-project' include 'subproject1' , 'subproject2' pluginManagement { repositories { gradlePluginPortal() mavenCentral() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() } }
3.3 创建Gradle项目 方法1:使用Gradle init(推荐)
1 2 3 4 5 6 7 8 9 10 11 12 gradle init --type java-application --dsl groovy --test-framework junit-jupiter gradle init --type java-library --dsl kotlin --test-framework spock gradle init --type java-application --dsl groovy gradle init
方法2:手动创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 mkdir my-gradle-project && cd my-gradle-projectmkdir -p src/main/java/com/examplemkdir -p src/main/resourcesmkdir -p src/test/java/com/examplemkdir -p src/test/resourcestouch build.gradletouch settings.gradletouch gradle.propertiesgradle wrapper --gradle-version 8.4
📝 最小化build.gradle示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 plugins { id 'java' } repositories { mavenCentral() } dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } tasks.named('test' ) { useJUnitPlatform() }
📌 第二阶段:Gradle DSL 语法与构建脚本 📝 4. Groovy DSL 深度解析 4.1 Groovy DSL 基础语法 🎯 基本语法特性
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 println 'Hello Gradle' println('Hello Gradle' ) def version = '1.0.0' println "Current version: ${version}" println "Current version: $version" def myClosure = { param -> println "Parameter: $param" } myClosure('test' ) def list = ['java' , 'kotlin' , 'scala' ]list.each { language -> println "Language: $language" } def config = [ version: '1.0.0' , encoding: 'UTF-8' ] println config.version
🔧 Gradle DSL 核心概念
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 android { compileSdkVersion 33 defaultConfig { applicationId "com.example.app" minSdkVersion 21 } } task myTask { doLast { println 'Executing myTask' } } dependencies { implementation 'org.springframework:spring-core:5.3.21' testImplementation 'junit:junit:4.13.2' } project.version = '1.0.0' version = '1.0.0'
4.2 构建脚本结构详解 📋 完整的build.gradle结构
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 plugins { id 'java' id 'application' id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' if (project.hasProperty('android' )) { id 'com.android.application' } } group = 'com.example' version = '1.0.0-SNAPSHOT' description = 'My Gradle Project' java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 withJavadocJar() withSourcesJar() } repositories { mavenLocal() mavenCentral() gradlePluginPortal() maven { name = 'Aliyun' url = 'https://maven.aliyun.com/repository/public' } maven { name = 'Spring Milestones' url = 'https://repo.spring.io/milestone' mavenContent { includeGroupByRegex 'org\\.springframework.*' includeGroup 'org.springframework.boot' includeGroup 'org.springframework.cloud' } } maven { name = 'CompanyNexus' url = 'https://nexus.company.com/repository/maven-public/' credentials { username = project.findProperty('nexusUsername' ) ?: 'guest' password = project.findProperty('nexusPassword' ) ?: 'guest' } authentication { basic(BasicAuthentication) } } maven { name = 'CompanySnapshots' url = 'https://nexus.company.com/repository/maven-snapshots/' credentials { username = project.findProperty('nexusUsername' ) password = project.findProperty('nexusPassword' ) } mavenContent { snapshotsOnly() } } if (project.hasProperty('useInternalRepo' )) { maven { name = 'InternalRepo' url = 'https://internal.company.com/repository/' } } } repositories { if (project.hasProperty('dev' )) { mavenLocal() maven { url 'https://maven.aliyun.com/repository/public' } mavenCentral() } else { mavenCentral() maven { url 'https://nexus.company.com/repository/maven-public/' credentials { username nexusUsername password nexusPassword } } } } ext { springBootVersion = '2.7.0' junitVersion = '5.9.2' mockitoVersion = '4.11.0' } dependencies { implementation "org.springframework.boot:spring-boot-starter-web:${springBootVersion}" implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3' compileOnly 'javax.servlet:javax.servlet-api:4.0.1' compileOnly 'org.projectlombok:lombok:1.18.24' runtimeOnly 'mysql:mysql-connector-java:8.0.33' runtimeOnly 'com.h2database:h2:2.1.214' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok:1.18.24' testImplementation "org.junit.jupiter:junit-jupiter:${junitVersion}" testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.testcontainers:junit-jupiter:1.17.3' testImplementation 'org.testcontainers:mysql:1.17.3' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'mysql:mysql-connector-java' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'io.micrometer:micrometer-registry-prometheus' implementation 'org.apache.commons:commons-lang3' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.testcontainers:mysql' testRuntimeOnly 'com.h2database:h2' } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation 'org.springframework.cloud:spring-cloud-starter-config' implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer' implementation 'org.springframework.boot:spring-boot-starter-amqp' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-actuator' } tasks.named('test' ) { useJUnitPlatform() jvmArgs = ['-Xmx1024m' ] systemProperty 'spring.profiles.active' , 'test' reports { html.required = true junitXml.required = true } testLogging { events 'passed' , 'skipped' , 'failed' exceptionFormat = 'full' } } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' options.compilerArgs += ['-parameters' , '-Xlint:unchecked' ] } jar { manifest { attributes( 'Implementation-Title' : project.name, 'Implementation-Version' : project.version, 'Main-Class' : 'com.example.Application' ) } exclude 'META-INF/*.RSA' , 'META-INF/*.SF' , 'META-INF/*.DSA' } task printProjectInfo { group = 'help' description = '打印项目信息' doLast { println "Project: ${project.name}" println "Version: ${project.version}" println "Java Version: ${java.sourceCompatibility}" println "Dependencies: ${configurations.runtimeClasspath.files.size()}" } } application { mainClass = 'com.example.Application' applicationDefaultJvmArgs = ['-Xmx512m' ] } publishing { publications { maven(MavenPublication) { from components.java pom { name = project.name description = project.description url = 'https://github.com/example/my-project' licenses { license { name = 'Apache License 2.0' url = 'https://www.apache.org/licenses/LICENSE-2.0' } } developers { developer { id = 'johndoe' name = 'John Doe' email = 'john@example.com' } } } } } repositories { maven { name = 'CompanyNexus' url = version.endsWith('SNAPSHOT' ) ? 'https://nexus.company.com/repository/maven-snapshots/' : 'https://nexus.company.com/repository/maven-releases/' credentials { username = project.findProperty('nexusUsername' ) password = project.findProperty('nexusPassword' ) } } } }
4.3 Kotlin DSL 对比 📝 build.gradle.kts 示例
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 plugins { java application id("org.springframework.boot" ) version "2.7.0" } group = "com.example" version = "1.0.0" java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } repositories { mavenCentral() } dependencies { implementation("org.springframework.boot:spring-boot-starter-web" ) testImplementation("org.junit.jupiter:junit-jupiter:5.9.2" ) } tasks.named<Test>("test" ) { useJUnitPlatform() } application { mainClass.set ("com.example.Application" ) }
🔍 Groovy vs Kotlin DSL 对比
特性
Groovy DSL
Kotlin DSL
语法
动态、简洁
静态类型、严格
IDE支持
基础支持
优秀的代码补全和重构
性能
运行时解析
编译时检查
学习曲线
较平缓
需要Kotlin知识
错误检测
运行时
编译时
重构支持
有限
强大
🔍 5. 依赖管理深度实践 5.1 依赖配置详解 📦 依赖配置类型
配置
说明
编译时
运行时
测试时
传递性
implementation
实现依赖(推荐)
✅
✅
✅
❌
api
API依赖
✅
✅
✅
✅
compileOnly
仅编译时
✅
❌
✅
❌
runtimeOnly
仅运行时
❌
✅
✅
❌
testImplementation
测试实现
❌
❌
✅
❌
testCompileOnly
测试编译时
❌
❌
✅
❌
testRuntimeOnly
测试运行时
❌
❌
✅
❌
🔧 实际应用示例
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 dependencies { implementation 'org.springframework:spring-core:5.3.21' implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3' api 'org.apache.commons:commons-lang3:3.12.0' compileOnly 'javax.servlet:javax.servlet-api:4.0.1' compileOnly 'org.projectlombok:lombok:1.18.24' runtimeOnly 'mysql:mysql-connector-java:8.0.33' runtimeOnly 'com.h2database:h2:2.1.214' annotationProcessor 'org.projectlombok:lombok:1.18.24' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.mockito:mockito-core:4.11.0' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' }
5.2 版本管理策略 🎯 版本声明方式
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 dependencies { implementation 'org.springframework:spring-core:5.3.21' implementation "org.springframework:spring-core:${springVersion}" implementation "org.springframework:spring-core:${ext.springVersion}" implementation 'org.springframework:spring-core:5.+' implementation 'org.springframework:spring-core:[5.0,6.0)' implementation 'org.springframework:spring-core:latest.release' } ext { springVersion = '5.3.21' junitVersion = '5.9.2' mockitoVersion = '4.11.0' }
🔧 依赖约束和BOM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 dependencies { implementation platform('org.springframework.boot:spring-boot-dependencies:2.7.0' ) implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'com.fasterxml.jackson.core:jackson-core:2.14.0' } dependencyManagement { dependencies { dependency 'org.apache.commons:commons-lang3:3.12.0' dependency 'com.google.guava:guava:31.1-jre' } }
5.3 依赖冲突解决 🔍 查看依赖树
1 2 3 4 5 6 7 8 9 10 11 ./gradlew dependencies ./gradlew dependencies --configuration runtimeClasspath ./gradlew dependencyInsight --dependency spring-core ./gradlew dependencies --configuration runtimeClasspath | grep "(*)"
🛠️ 解决冲突策略
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 32 33 34 35 36 dependencies { implementation 'org.springframework:spring-core:5.3.21' implementation('org.springframework:spring-context:5.3.21' ) { exclude group: 'commons-logging' , module: 'commons-logging' } implementation('some.group:some-module:1.0' ) { transitive = false } implementation 'commons-logging:commons-logging:1.2' } configurations.all { resolutionStrategy { force 'commons-logging:commons-logging:1.2' failOnVersionConflict() cacheDynamicVersionsFor 10 , 'minutes' cacheChangingModulesFor 4 , 'hours' dependencySubstitution { substitute module('commons-logging:commons-logging' ) with module('org.slf4j:jcl-over-slf4j:1.7.36' ) } } }
📌 第三阶段:Gradle 任务系统与插件 ⚙️ 6. 任务系统深度解析 6.1 任务基础概念 🎯 任务的生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 task myTask { println 'Configuring myTask' doFirst { println 'Before myTask execution' } doLast { println 'After myTask execution' } } myTask { description = 'My custom task' group = 'custom' }
🔧 任务类型
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 32 33 34 35 36 37 task hello { doLast { println 'Hello, Gradle!' } } task copyFiles(type: Copy) { from 'src/main/resources' into 'build/resources' } task createZip(type: Zip) { from 'src/main/java' archiveFileName = 'sources.zip' destinationDirectory = file('build/distributions' ) } class GreetingTask extends DefaultTask { @Input String greeting = 'hello' @Input String recipient = 'world' @TaskAction void greet() { println "${greeting}, ${recipient}!" } } task greeting(type: GreetingTask) { greeting = 'Hi' recipient = 'Gradle' }
6.2 任务依赖与排序 🔗 任务依赖
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 32 task taskA { doLast { println 'Task A' } } task taskB { doLast { println 'Task B' } } task taskC { dependsOn taskA, taskB doLast { println 'Task C' } } task taskD { dependsOn tasks.matching { task -> task.name.startsWith('test' ) } doLast { println 'Task D' } } taskC.dependsOn { tasks.findAll { task -> task.name.startsWith('compile' ) && task.enabled } }
📋 任务排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 task taskX { doLast { println 'Task X' } } task taskY { doLast { println 'Task Y' } } taskY.mustRunAfter taskX taskY.shouldRunAfter taskX task cleanup { doLast { println 'Cleanup' } } taskX.finalizedBy cleanup
6.3 任务输入输出 📁 任务输入输出管理详解
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 task processFiles { inputs.files fileTree('src/main/resources' ) { include '**/*.properties' include '**/*.yml' exclude '**/*.tmp' } inputs.property 'version' , project.version inputs.property 'environment' , project.findProperty('env' ) ?: 'dev' outputs.dir 'build/processed' outputs.cacheIf { true } outputs.upToDateWhen { file('build/processed' ).exists() && file('build/processed' ).lastModified() > inputs.files.asFileTree.maxBy { it.lastModified() }.lastModified() } doLast { outputs.files.singleFile.mkdirs() copy { from inputs.files into outputs.files.singleFile filter { line -> line.replace('${version}' , project.version) .replace('${env}' , project.findProperty('env' ) ?: 'dev' ) } } println "Processed ${inputs.files.files.size()} files to ${outputs.files.singleFile}" } } class ProcessFilesTask extends DefaultTask { @InputFiles @PathSensitive (PathSensitivity.RELATIVE) FileCollection inputFiles @Input String version @Input @Optional String environment = 'dev' @OutputDirectory File outputDir @Internal String logLevel = 'INFO' @TaskAction void processFiles() { outputDir.mkdirs() inputFiles.each { file -> def outputFile = new File(outputDir, file.name) outputFile.text = file.text .replace('${version}' , version) .replace('${environment}' , environment) if (logLevel == 'DEBUG' ) { println "Processed: ${file.name} -> ${outputFile.name}" } } println "Processed ${inputFiles.files.size()} files for environment: ${environment}" } } tasks.register('processConfigFiles' , ProcessFilesTask) { inputFiles = fileTree('src/main/resources/config' ) version = project.version environment = project.findProperty('env' ) ?: 'dev' outputDir = file('build/processed-config' ) } task generateDocumentation { inputs.files fileTree('src/main/java' ) { include '**/*.java' } inputs.files fileTree('docs/templates' ) inputs.property 'version' , project.version inputs.property 'buildTime' , new Date().format('yyyy-MM-dd HH:mm:ss' ) outputs.dir 'build/docs/api' outputs.dir 'build/docs/user-guide' outputs.file 'build/docs/README.html' outputs.cacheIf { project.hasProperty('prod' ) } doLast { exec { commandLine 'javadoc' , '-d' , 'build/docs/api' , '-sourcepath' , 'src/main/java' , '-subpackages' , 'com.example' } copy { from 'docs/templates' into 'build/docs/user-guide' expand( version: project.version, buildTime: new Date().format('yyyy-MM-dd HH:mm:ss' ) ) } def readmeContent = """ # ${project.name} v${project.version} Generated on: ${new Date().format('yyyy-MM-dd HH:mm:ss')} ## API Documentation See [API Docs](api/index.html) ## User Guide See [User Guide](user-guide/index.html) """ .stripIndent() file('build/docs/README.html' ).text = readmeContent } } task copyResources(type: Copy) { from 'src/main/resources' into 'build/resources' filter { line -> line.replace('${project.version}' , project.version) } include '**/*.properties' exclude '**/*.tmp' } task createDistribution(type: Zip) { archiveFileName = "${project.name}-${project.version}.zip" destinationDirectory = file('build/distributions' ) from 'build/libs' from 'src/main/scripts' from 'README.md' } tasks.named('test' ) { inputs.files sourceSets.test.runtimeClasspath inputs.files sourceSets.main.runtimeClasspath inputs.property 'javaVersion' , System.getProperty('java.version' ) outputs.dir 'build/test-results' outputs.dir 'build/reports/tests' outputs.cacheIf { !project.hasProperty('rerunTests' ) } }
🔌 7. 插件系统详解 7.1 插件应用方式 📦 插件应用语法
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 plugins { id 'java' id 'application' } plugins { id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' } apply plugin: 'java' apply plugin: 'application' plugins { id 'java' if (project.hasProperty('android' )) { id 'com.android.application' } } apply from: 'gradle/dependencies.gradle' apply from: 'https://raw.githubusercontent.com/example/scripts/main/common.gradle'
7.2 常用插件详解 ☕ Java插件
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 32 33 34 35 plugins { id 'java' } java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 withSourcesJar() withJavadocJar() } compileJava { options.encoding = 'UTF-8' options.compilerArgs += ['-parameters' , '-Xlint:unchecked' ] } test { useJUnitPlatform() testLogging { events 'passed' , 'skipped' , 'failed' } reports { html.required = true junitXml.required = true } }
🌐 Application插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 plugins { id 'application' } application { mainClass = 'com.example.Application' applicationDefaultJvmArgs = ['-Xmx512m' , '-Dfile.encoding=UTF-8' ] }
🌸 Spring Boot插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 plugins { id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' } springBoot { buildInfo() mainClass = 'com.example.Application' }
📌 第四阶段:多项目构建与高级特性 🏗️ 8. 多项目构建管理 多项目构建是Gradle的核心优势之一,能够高效管理复杂的企业级项目结构。
8.1 多项目结构设计 📁 典型多项目结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 my-multi-project/ ├── settings.gradle ├── build.gradle ├── gradle.properties ├── gradle/ │ └── wrapper/ ├── buildSrc/ │ ├── build.gradle │ └── src/main/groovy/ ├── common/ │ ├── build.gradle │ └── src/ ├── api/ │ ├── build.gradle │ └── src/ ├── service/ │ ├── build.gradle │ └── src/ ├── web/ │ ├── build.gradle │ └── src/ └── integration-tests/ ├── build.gradle └── src/
8.2 根项目配置 ⚙️ settings.gradle 详细配置
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 rootProject.name = 'my-multi-project' include 'common' include 'api' include 'service' include 'web' include 'integration-tests' include 'common:common-core' include 'common:common-web' include 'common:common-data' include 'services:user-service' include 'services:order-service' include 'services:payment-service' include 'infrastructure:config-server' include 'infrastructure:eureka-server' project(':common' ).projectDir = file('modules/common' ) project(':api' ).projectDir = file('modules/api' ) ['user-service' , 'order-service' , 'payment-service' ].each { serviceName -> project(":services:${serviceName}" ).projectDir = file("services/${serviceName}" ) } pluginManagement { repositories { gradlePluginPortal() mavenCentral() maven { url = 'https://nexus.company.com/repository/gradle-plugins/' credentials { username = providers.gradleProperty('nexusUsername' ).orNull password = providers.gradleProperty('nexusPassword' ).orNull } } } plugins { id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'jacoco' version '0.8.8' id 'com.github.spotbugs' version '5.0.9' id 'checkstyle' version '10.3.1' id 'com.palantir.docker' version '0.34.0' id 'com.google.cloud.tools.jib' version '3.2.1' id 'org.asciidoctor.jvm.convert' version '3.3.2' id 'com.gradle.build-scan' version '3.11' } resolutionStrategy { eachPlugin { if (requested.id.namespace == 'com.company' ) { useModule('com.company:gradle-plugins:1.0.0' ) } } } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { if (providers.gradleProperty('useLocalRepo' ).isPresent()) { mavenLocal() } maven { name = 'CompanyNexus' url = 'https://nexus.company.com/repository/maven-public/' credentials { username = providers.gradleProperty('nexusUsername' ).orNull password = providers.gradleProperty('nexusPassword' ).orNull } } maven { name = 'Aliyun' url = 'https://maven.aliyun.com/repository/public' } mavenCentral() maven { name = 'SpringRepo' url = 'https://repo.spring.io/milestone' mavenContent { includeGroupByRegex 'org\\.springframework.*' } } } versionCatalogs { libs { version('spring-boot' , '2.7.0' ) version('spring-cloud' , '2021.0.3' ) version('junit' , '5.9.2' ) library('spring-boot-starter-web' , 'org.springframework.boot' , 'spring-boot-starter-web' ).versionRef('spring-boot' ) library('spring-boot-starter-test' , 'org.springframework.boot' , 'spring-boot-starter-test' ).versionRef('spring-boot' ) library('junit-jupiter' , 'org.junit.jupiter' , 'junit-jupiter' ).versionRef('junit' ) plugin('spring-boot' , 'org.springframework.boot' ).versionRef('spring-boot' ) plugin('spring-dependency-management' , 'io.spring.dependency-management' ).version('1.0.11.RELEASE' ) bundle('spring-boot-web' , ['spring-boot-starter-web' , 'spring-boot-starter-actuator' ]) bundle('testing' , ['junit-jupiter' , 'spring-boot-starter-test' ]) } } } buildCache { local { enabled = true directory = file('build-cache' ) removeUnusedEntriesAfterDays = 30 } remote(HttpBuildCache) { url = 'https://cache.company.com/' push = providers.gradleProperty('pushToCache' ).isPresent() credentials { username = providers.gradleProperty('cacheUsername' ).orNull password = providers.gradleProperty('cachePassword' ).orNull } } } enableFeaturePreview('TYPESAFE_PROJECT_ACCESSORS' ) enableFeaturePreview('VERSION_CATALOGS' )
💡 settings.gradle配置实战案例
案例1:大型企业项目配置
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 rootProject.name = 'enterprise-platform' include 'platform-core' include 'platform-common' include 'platform-security' ['user' , 'order' , 'payment' , 'inventory' ].each { module -> include "business-${module}" project(":business-${module}" ).projectDir = file("business/${module}" ) } ['gateway' , 'config' , 'registry' , 'monitor' ].each { infra -> include "infra-${infra}" project(":infra-${infra}" ).projectDir = file("infrastructure/${infra}" ) } pluginManagement { repositories { maven { url = 'https://nexus.corp.com/repository/gradle-plugins/' credentials { username = System.getenv('CORP_NEXUS_USER' ) password = System.getenv('CORP_NEXUS_PASS' ) } } gradlePluginPortal() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url = 'https://nexus.corp.com/repository/maven-public/' credentials { username = System.getenv('CORP_NEXUS_USER' ) password = System.getenv('CORP_NEXUS_PASS' ) } } mavenCentral() } }
案例2:开源项目配置
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 32 33 34 35 rootProject.name = 'awesome-library' include 'core' include 'extensions' include 'examples' include 'benchmarks' pluginManagement { repositories { gradlePluginPortal() mavenCentral() } plugins { id 'java-library' id 'maven-publish' id 'signing' id 'org.gradle.test-retry' version '1.4.1' id 'com.gradle.plugin-publish' version '1.0.0' } } dependencyResolutionManagement { repositories { mavenCentral() maven { url = 'https://oss.sonatype.org/content/repositories/snapshots/' mavenContent { snapshotsOnly() } } } }
📋 根项目 build.gradle
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 allprojects { group = 'com.example' version = '1.0.0-SNAPSHOT' repositories { mavenCentral() } } subprojects { apply plugin: 'java' apply plugin: 'java-library' java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } dependencies { implementation 'org.slf4j:slf4j-api:1.7.36' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' options.compilerArgs += ['-parameters' ] } test { useJUnitPlatform() testLogging { events 'passed' , 'skipped' , 'failed' } } } project(':web' ) { apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' dependencies { implementation project(':service' ) implementation 'org.springframework.boot:spring-boot-starter-web' } } project(':service' ) { dependencies { implementation project(':api' ) implementation project(':common' ) implementation 'org.springframework.boot:spring-boot-starter' } } project(':api' ) { dependencies { api project(':common' ) api 'javax.validation:validation-api:2.0.1.Final' } } task buildAll { dependsOn subprojects.collect { it.tasks.named('build' ) } description = '构建所有子项目' group = 'build' } task testAll { dependsOn subprojects.collect { it.tasks.named('test' ) } description = '测试所有子项目' group = 'verification' }
8.3 子项目配置示例 📦 common模块 (common/build.gradle)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 dependencies { api 'org.apache.commons:commons-lang3:3.12.0' api 'com.fasterxml.jackson.core:jackson-databind:2.13.3' api 'com.google.guava:guava:31.1-jre' implementation 'org.slf4j:slf4j-api:1.7.36' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation 'org.assertj:assertj-core:3.23.1' } java { withSourcesJar() withJavadocJar() }
🔧 service模块 (service/build.gradle)
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 32 plugins { id 'org.springframework.boot' id 'io.spring.dependency-management' } dependencies { implementation project(':api' ) implementation project(':common' ) implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' runtimeOnly 'mysql:mysql-connector-java' testImplementation 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' } jar { enabled = true archiveClassifier = '' } bootJar { enabled = false }
🌐 web模块 (web/build.gradle)
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 32 33 34 35 plugins { id 'org.springframework.boot' id 'io.spring.dependency-management' } dependencies { implementation project(':service' ) implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-validation' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.boot:spring-boot-testcontainers' testImplementation 'org.testcontainers:mysql' } springBoot { buildInfo() mainClass = 'com.example.web.WebApplication' } task buildImage { dependsOn bootBuildImage description = '构建Docker镜像' group = 'build' }
8.4 多项目构建命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ./gradlew build ./gradlew :web:build ./gradlew :service:test ./gradlew :web:bootRun ./gradlew projects ./gradlew :web:tasks ./gradlew build --parallel ./gradlew :web:build --include-build ./gradlew build --continuous
🔌 9. 自定义插件开发 9.1 插件开发方式 📝 脚本插件(简单场景)
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 32 33 ext { springBootVersion = '2.7.0' junitVersion = '5.9.2' } configurations { integrationTestImplementation.extendsFrom testImplementation integrationTestRuntimeOnly.extendsFrom testRuntimeOnly } sourceSets { integrationTest { java.srcDir 'src/integration-test/java' resources.srcDir 'src/integration-test/resources' } } task integrationTest(type: Test) { testClassesDirs = sourceSets.integrationTest.output.classesDirs classpath = sourceSets.integrationTest.runtimeClasspath useJUnitPlatform() testLogging { events 'passed' , 'skipped' , 'failed' } }
🏗️ buildSrc插件(项目级插件)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 plugins { id 'groovy-gradle-plugin' } repositories { gradlePluginPortal() mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-gradle-plugin:2.7.0' } plugins { id 'java' id 'jacoco' } java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 withSourcesJar() withJavadocJar() } repositories { mavenCentral() } dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' options.compilerArgs += ['-parameters' , '-Xlint:unchecked' ] } test { useJUnitPlatform() finalizedBy jacocoTestReport } jacocoTestReport { dependsOn test reports { xml.required = true html.required = true } }
🎯 独立插件项目
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 plugins { id 'java-gradle-plugin' id 'groovy' id 'maven-publish' } group = 'com.example' version = '1.0.0' repositories { gradlePluginPortal() mavenCentral() } dependencies { implementation gradleApi() implementation localGroovy() testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0' } gradlePlugin { plugins { myPlugin { id = 'com.example.my-plugin' implementationClass = 'com.example.MyPlugin' displayName = 'My Custom Plugin' description = 'A custom Gradle plugin' } } } publishing { repositories { maven { url = 'https://nexus.company.com/repository/gradle-plugins/' credentials { username = project.findProperty('nexusUsername' ) password = project.findProperty('nexusPassword' ) } } } }
9.2 插件实现示例 🎯 自定义任务类
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 package com.example.tasksimport org.gradle.api.DefaultTaskimport org.gradle.api.tasks.*class GreetingTask extends DefaultTask { @Input String greeting = 'Hello' @Input String recipient = 'World' @OutputFile File outputFile @TaskAction void greet() { def message = "${greeting}, ${recipient}!" println message if (outputFile) { outputFile.parentFile.mkdirs() outputFile.text = message } } }
🔌 插件主类
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 32 33 34 35 36 37 38 package com.exampleimport com.example.tasks.GreetingTaskimport org.gradle.api.Pluginimport org.gradle.api.Projectclass MyPlugin implements Plugin <Project> { @Override void apply(Project project) { def extension = project.extensions.create('myPlugin' , MyPluginExtension) project.tasks.register('greeting' , GreetingTask) { task -> task.greeting = extension.greeting task.recipient = extension.recipient task.outputFile = project.file("${project.buildDir}/greeting.txt" ) } project.tasks.named('build' ) { dependsOn 'greeting' } project.afterEvaluate { println "MyPlugin applied to ${project.name}" } } } class MyPluginExtension { String greeting = 'Hello' String recipient = 'Gradle' }
📝 使用自定义插件
1 2 3 4 5 6 7 8 9 plugins { id 'com.example.my-plugin' version '1.0.0' } myPlugin { greeting = 'Hi' recipient = 'Developer' }
⚡ 10. 性能优化与最佳实践 10.1 构建性能优化 🚀 Gradle Daemon优化详解
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 32 33 34 35 36 37 38 org.gradle.daemon =true org.gradle.daemon.idletimeout =3600000 org.gradle.jvmargs =-Xmx4g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
💡 Daemon优化实战案例
案例1:开发环境优化配置
1 2 3 4 5 6 7 8 9 10 11 org.gradle.daemon =true org.gradle.jvmargs =-Xmx8g -XX:MaxMetaspaceSize=1g -XX:+UseG1GC org.gradle.daemon.idletimeout =7200000 # 2小时超时 org.gradle.parallel =true org.gradle.configureondemand =true org.gradle.caching =true org.gradle.vfs.watch =true # 文件系统监控(Gradle 6.5+)
案例2:CI/CD环境配置
1 2 3 4 5 6 7 8 9 10 11 org.gradle.daemon =false # CI环境不使用daemon org.gradle.jvmargs =-Xmx4g -XX:MaxMetaspaceSize=512m org.gradle.parallel =true # 启用并行构建 org.gradle.caching =true # 启用构建缓存 org.gradle.console =plain # 纯文本输出 org.gradle.logging.level =info # 详细日志 org.gradle.warning.mode =fail # 警告时失败
案例3:容器环境配置
1 2 3 4 5 6 org.gradle.daemon =false # 容器中不使用daemon org.gradle.jvmargs =-Xmx2g -XX:MaxMetaspaceSize=256m -XX:+UseSerialGC org.gradle.parallel =false # 容器中禁用并行(避免资源竞争) org.gradle.workers.max =2 # 限制工作线程数
🔄 并行构建优化
1 2 3 4 5 6 7 8 9 org.gradle.parallel =true org.gradle.workers.max =4 org.gradle.configureondemand =true
💾 构建缓存优化详解
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 org.gradle.caching =true org.gradle.caching.debug =true org.gradle.unsafe.configuration-cache =true org.gradle.unsafe.configuration-cache-problems =warn // build.gradle - 构建缓存详细配置 buildCache { // ==================== 本地缓存配置 ==================== local { enabled = true // 缓存目录:默认在 ~/.gradle/caches/build-cache-1 directory = file('build-cache') // 清理策略:30天后删除未使用的缓存条目 removeUnusedEntriesAfterDays = 30 // 缓存大小限制(可选) // targetSizeInMB = 5000 // 限制为5GB } // ==================== 远程缓存配置 ==================== remote(HttpBuildCache) { // 远程缓存服务器URL url = 'https://cache.company.com/' // 推送权限:只有CI环境推送缓存 push = project.hasProperty('ci') || System.getenv('CI') != null // 认证信息 credentials { username = project.findProperty('cacheUsername') ?: System.getenv('CACHE_USERNAME') password = project.findProperty('cachePassword') ?: System.getenv('CACHE_PASSWORD') } // 连接配置 allowUntrustedServer = false allowInsecureProtocol = false // 超时配置 // connectionTimeoutMs = 30000 // socketTimeoutMs = 30000 } } // ==================== 任务缓存配置 ==================== // 为自定义任务启用缓存 tasks.register('processFiles', ProcessFilesTask) { // 输入文件 inputFiles.from(fileTree('src/main/resources')) // 输出目录 outputDir = file('build/processed') // 启用缓存 outputs.cacheIf { true } // 缓存键配置 inputs.property('version', project.version) inputs.property('environment', project.findProperty('env') ?: 'dev') } // 禁用特定任务的缓存 tasks.named('someTask') { outputs.doNotCacheIf('Task has side effects') { true } } // ==================== 缓存策略配置 ==================== // 全局缓存策略 tasks.withType(JavaCompile).configureEach { // 启用增量编译 options.incremental = true // 缓存配置 outputs.cacheIf { true } } tasks.withType(Test).configureEach { // 测试任务缓存配置 outputs.cacheIf { // 只有在没有系统属性变化时才缓存 } }
💡 构建缓存实战案例
案例1:企业级缓存配置
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 buildCache { local { enabled = true directory = file('/opt/gradle-cache' ) removeUnusedEntriesAfterDays = 7 } remote(HttpBuildCache) { url = 'https://gradle-cache.company.com/' push = (System.getenv('CI' ) != null ) && (System.getenv('BRANCH_NAME' ) in ['main' , 'develop' ]) credentials { username = System.getenv('GRADLE_CACHE_USER' ) password = System.getenv('GRADLE_CACHE_PASS' ) } allowUntrustedServer = false connectionTimeoutMs = 10000 socketTimeoutMs = 30000 } }
案例2:开源项目缓存配置
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 buildCache { local { enabled = true removeUnusedEntriesAfterDays = 14 } remote(HttpBuildCache) { url = 'https://ge.gradle.org/cache/' push = false } } tasks.withType(Javadoc).configureEach { outputs.cacheIf { true } } tasks.withType(Test).configureEach { outputs.cacheIf { !project.hasProperty('forceTests' ) } }
案例3:多环境缓存策略
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 buildCache { local { enabled = true directory = file("${System.getProperty('user.home')}/.gradle/build-cache" ) removeUnusedEntriesAfterDays = project.hasProperty('dev' ) ? 7 : 30 } remote(HttpBuildCache) { def cacheUrl = project.findProperty('cacheUrl' ) ?: System.getenv('GRADLE_CACHE_URL' ) if (cacheUrl) { url = cacheUrl push = project.hasProperty('pushCache' ) || System.getenv('GRADLE_CACHE_PUSH' ) == 'true' credentials { username = project.findProperty('cacheUser' ) ?: System.getenv('GRADLE_CACHE_USER' ) password = project.findProperty('cachePass' ) ?: System.getenv('GRADLE_CACHE_PASS' ) } } } }
🎯 11. 环境配置管理实战 11.1 多环境配置策略 📝 gradle.properties 环境配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 version =1.0.0-SNAPSHOT group =com.example spring.profiles.active =dev database.url =jdbc:mysql://localhost:3306/myapp_dev database.username =dev_user database.password =dev_password redis.host =localhost redis.port =6379 log.level =DEBUG
🔧 build.gradle 环境配置处理
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 def environment = project.findProperty('env' ) ?: 'dev' def isProduction = environment == 'prod' def isDevelopment = environment == 'dev' def isTesting = environment == 'test' ext { env = environment dbUrl = project.findProperty('database.url' ) ?: 'jdbc:h2:mem:testdb' dbUsername = project.findProperty('database.username' ) ?: 'sa' dbPassword = project.findProperty('database.password' ) ?: '' redisHost = project.findProperty('redis.host' ) ?: 'localhost' redisPort = project.findProperty('redis.port' ) ?: '6379' logLevel = project.findProperty('log.level' ) ?: 'INFO' springProfiles = project.findProperty('spring.profiles.active' ) ?: 'dev' } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' if (isDevelopment) { developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.h2database:h2' } if (isProduction) { runtimeOnly 'mysql:mysql-connector-java' implementation 'io.micrometer:micrometer-registry-prometheus' } if (isTesting) { testImplementation 'org.testcontainers:mysql' testImplementation 'org.testcontainers:redis' } } tasks.named('bootRun' ) { systemProperty 'spring.profiles.active' , springProfiles systemProperty 'database.url' , dbUrl systemProperty 'database.username' , dbUsername systemProperty 'database.password' , dbPassword systemProperty 'redis.host' , redisHost systemProperty 'redis.port' , redisPort if (isDevelopment) { systemProperty 'spring.devtools.restart.enabled' , 'true' systemProperty 'logging.level.com.example' , 'DEBUG' } } tasks.named('test' ) { systemProperty 'spring.profiles.active' , 'test' systemProperty 'database.url' , 'jdbc:h2:mem:testdb' jvmArgs = ['-Xmx1024m' , '-XX:MaxMetaspaceSize=256m' ] } tasks.named('processResources' ) { filesMatching(['**/*.properties' , '**/*.yml' ]) { expand( version: project.version, environment: environment, databaseUrl: dbUrl, databaseUsername: dbUsername, redisHost: redisHost, redisPort: redisPort, logLevel: logLevel ) } }
11.2 配置文件管理策略 📁 配置文件结构
1 2 3 4 5 6 7 8 9 10 11 12 src/main/resources/ ├── application.yml ├── application-dev.yml ├── application-test.yml ├── application-prod.yml ├── config/ │ ├── database-dev.properties │ ├── database-test.properties │ └── database-prod.properties └── templates/ ├── application.yml.template └── logback-spring.xml.template
📝 application.yml 模板
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 32 33 34 35 36 37 38 39 40 41 server: port: 8080 servlet: context-path: /api spring: profiles: active: ${environment} application: name: ${project.name} version: ${version} datasource: url: ${databaseUrl} username: ${databaseUsername} password: ${databasePassword} driver-class-name: com.mysql.cj.jdbc.Driver redis: host: ${redisHost} port: ${redisPort} database: 0 logging: level: com.example: ${logLevel} org.springframework: INFO pattern: console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{traceId}] %logger{50} - %msg%n" management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: when-authorized
11.3 环境配置实战案例 案例1:多环境构建脚本
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 def environmentConfigs = [ dev: [ profile: 'dev' , dbUrl: 'jdbc:mysql://localhost:3306/myapp_dev' , dbUser: 'dev_user' , dbPass: 'dev_password' , redisHost: 'localhost' , logLevel: 'DEBUG' , skipTests: false ], test: [ profile: 'test' , dbUrl: 'jdbc:mysql://test-server:3306/myapp_test' , dbUser: 'test_user' , dbPass: System.getenv('TEST_DB_PASSWORD' ), redisHost: 'test-redis.company.com' , logLevel: 'INFO' , skipTests: false ], prod: [ profile: 'prod' , dbUrl: 'jdbc:mysql://prod-cluster:3306/myapp_prod' , dbUser: 'prod_user' , dbPass: System.getenv('PROD_DB_PASSWORD' ), redisHost: 'prod-redis-cluster.company.com' , logLevel: 'WARN' , skipTests: true ] ] def currentEnv = project.findProperty('env' ) ?: 'dev' def config = environmentConfigs[currentEnv]if (!config) { throw new GradleException("Unknown environment: ${currentEnv}" ) } ext { environmentConfig = config } task deployToEnvironment { group = 'deployment' description = "Deploy to ${currentEnv} environment" doLast { println "Deploying to ${currentEnv} environment..." println "Database: ${config.dbUrl}" println "Redis: ${config.redisHost}" println "Log Level: ${config.logLevel}" if (config.skipTests) { println "Skipping tests for ${currentEnv} environment" } else { println "Running tests for ${currentEnv} environment" } } } task validateEnvironment { group = 'verification' description = "Validate ${currentEnv} environment configuration" doLast { println "Validating ${currentEnv} environment..." def requiredEnvVars = [] if (currentEnv == 'test' ) { requiredEnvVars = ['TEST_DB_PASSWORD' ] } else if (currentEnv == 'prod' ) { requiredEnvVars = ['PROD_DB_PASSWORD' , 'PROD_REDIS_PASSWORD' ] } requiredEnvVars.each { envVar -> if (!System.getenv(envVar)) { throw new GradleException("Required environment variable not set: ${envVar}" ) } } println "Environment validation passed for ${currentEnv}" } } tasks.named('build' ) { dependsOn validateEnvironment }
案例2:Docker多环境构建
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 apply plugin: 'com.palantir.docker' docker { name = "${project.name}:${project.version}-${currentEnv}" dockerfile file('docker/Dockerfile' ) buildArgs([ 'JAR_FILE' : "build/libs/${project.name}-${project.version}.jar" , 'ENVIRONMENT' : currentEnv, 'JAVA_OPTS' : getJavaOpts(currentEnv) ]) files tasks.bootJar.outputs.files files 'docker/entrypoint.sh' files "src/main/resources/application-${currentEnv}.yml" } def getJavaOpts(env) { def javaOpts = [ dev: '-Xmx1g -Xms512m -XX:+UseG1GC' , test: '-Xmx2g -Xms1g -XX:+UseG1GC' , prod: '-Xmx4g -Xms2g -XX:+UseG1GC -XX:+UseStringDeduplication' ] return javaOpts[env] ?: javaOpts['dev' ] } task buildDockerDev { group = 'docker' description = 'Build Docker image for development' dependsOn 'bootJar' finalizedBy 'docker' doFirst { project.ext.currentEnv = 'dev' } } task buildDockerProd { group = 'docker' description = 'Build Docker image for production' dependsOn 'bootJar' finalizedBy 'docker' doFirst { project.ext.currentEnv = 'prod' } }
📊 增量构建优化
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 task processFiles { inputs.files fileTree('src/main/resources' ) inputs.property 'version' , project.version outputs.dir 'build/processed' outputs.cacheIf { true } doLast { } } class ProcessTask extends DefaultTask { @InputFiles @PathSensitive (PathSensitivity.RELATIVE) FileCollection inputFiles @Input String version @OutputDirectory File outputDir @TaskAction void process() { } }
10.2 依赖解析优化 🔍 依赖解析策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 configurations.all { resolutionStrategy { cacheDynamicVersionsFor 10 , 'minutes' cacheChangingModulesFor 4 , 'hours' componentSelection { all { ComponentSelection selection -> if (selection.candidate.version.contains('alpha' )) { selection.reject('Alpha versions not allowed' ) } } } dependencySubstitution { substitute module('commons-logging:commons-logging' ) with module('org.slf4j:jcl-over-slf4j:1.7.36' ) } } }
📦 仓库优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 repositories { mavenLocal() maven { name = 'Aliyun' url = 'https://maven.aliyun.com/repository/public' } maven { url = 'https://repo.spring.io/milestone' mavenContent { includeGroupByRegex 'org\\.springframework.*' } } mavenCentral() }
10.3 构建脚本优化 🎯 避免配置时间过长
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 task badTask { def result = expensiveOperation() doLast { println result } } task goodTask { doLast { def result = expensiveOperation() println result } } def expensiveProvider = providers.provider { expensiveOperation() } task betterTask { doLast { println expensiveProvider.get() } }
🔧 任务配置优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 tasks.configureEach { task -> if (task instanceof Test) { task.useJUnitPlatform() task.testLogging { events 'passed' , 'skipped' , 'failed' } } } tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.compilerArgs.addAll(['-parameters' , '-Xlint:unchecked' ]) }
📌 第五阶段:实战案例与企业级应用 🎯 11. 实战案例:Spring Boot微服务项目 11.1 项目结构设计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 microservice-project/ ├── settings.gradle ├── build.gradle ├── gradle.properties ├── buildSrc/ │ ├── build.gradle │ └── src /main /groovy/ ├── common/ │ ├── common-core/ │ ├── common-web/ │ └── common-data/ ├── services/ │ ├── user-service/ │ ├── order -service/ │ └── payment-service/ ├── gateway/ │ └── api-gateway/ ├── infrastructure/ │ ├── config-server/ │ ├── eureka-server/ │ └── monitoring/ └── docker/ ├── docker-compose.yml └── Dockerfile.template
11.2 根项目配置 ⚙️ settings.gradle
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 rootProject.name = 'microservice-project' include 'common:common-core' include 'common:common-web' include 'common:common-data' include 'services:user-service' include 'services:order-service' include 'services:payment-service' include 'gateway:api-gateway' include 'infrastructure:config-server' include 'infrastructure:eureka-server' include 'infrastructure:monitoring' pluginManagement { plugins { id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'com.palantir.docker' version '0.34.0' id 'com.google.cloud.tools.jib' version '3.2.1' } }
📋 根项目 build.gradle
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 plugins { id 'java' id 'org.springframework.boot' version '2.7.0' apply false id 'io.spring.dependency-management' version '1.0.11.RELEASE' apply false } ext { springBootVersion = '2.7.0' springCloudVersion = '2021.0.3' testcontainersVersion = '1.17.3' } allprojects { group = 'com.example.microservice' version = '1.0.0-SNAPSHOT' repositories { maven { url 'https://maven.aliyun.com/repository/public' } mavenCentral() } } subprojects { apply plugin: 'java' apply plugin: 'io.spring.dependency-management' java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } dependencyManagement { imports { mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}" mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}" } } dependencies { implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-actuator' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.testcontainers:junit-jupiter' } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' options.compilerArgs += ['-parameters' ] } test { useJUnitPlatform() testLogging { events 'passed' , 'skipped' , 'failed' } } } configure(subprojects.findAll { it.path.startsWith(':services:' ) }) { apply plugin: 'org.springframework.boot' dependencies { implementation project(':common:common-core' ) implementation project(':common:common-web' ) implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' } } configure(subprojects.findAll { it.path.startsWith(':common:' ) }) { jar { enabled = true archiveClassifier = '' } bootJar { enabled = false } }
11.3 服务模块配置示例 🔧 user-service/build.gradle
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 plugins { id 'org.springframework.boot' id 'com.google.cloud.tools.jib' } dependencies { implementation project(':common:common-core' ) implementation project(':common:common-web' ) implementation project(':common:common-data' ) implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation 'org.springframework.cloud:spring-cloud-starter-config' implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' runtimeOnly 'mysql:mysql-connector-java' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.testcontainers:mysql' } springBoot { buildInfo() mainClass = 'com.example.microservice.user.UserServiceApplication' } jib { from { image = 'openjdk:11-jre-slim' } to { image = "microservice/${project.name}:${project.version}" tags = ['latest' ] } container { jvmFlags = ['-Xmx512m' , '-Dfile.encoding=UTF-8' ] ports = ['8080' ] environment = [ 'SPRING_PROFILES_ACTIVE' : 'docker' ] } } configurations { integrationTestImplementation.extendsFrom testImplementation integrationTestRuntimeOnly.extendsFrom testRuntimeOnly } sourceSets { integrationTest { java.srcDir 'src/integration-test/java' resources.srcDir 'src/integration-test/resources' } } task integrationTest(type: Test) { testClassesDirs = sourceSets.integrationTest.output.classesDirs classpath = sourceSets.integrationTest.runtimeClasspath useJUnitPlatform() shouldRunAfter test testLogging { events 'passed' , 'skipped' , 'failed' } } check.dependsOn integrationTest
11.4 构建脚本优化 🎯 buildSrc/src/main/groovy/microservice-conventions.gradle
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 plugins { id 'java' id 'org.springframework.boot' id 'io.spring.dependency-management' id 'jacoco' } java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 withSourcesJar() } dependencies { implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' implementation 'io.micrometer:micrometer-registry-prometheus' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.testcontainers:junit-jupiter' } test { useJUnitPlatform() finalizedBy jacocoTestReport testLogging { events 'passed' , 'skipped' , 'failed' exceptionFormat = 'full' } } jacocoTestReport { dependsOn test reports { xml.required = true html.required = true } afterEvaluate { classDirectories.setFrom(files(classDirectories.files.collect { fileTree(dir: it, exclude: [ '**/config/**' , '**/dto/**' , '**/entity/**' , '**/*Application.*' ]) })) } } task healthCheck { group = 'verification' description = '执行服务健康检查' doLast { def port = project.findProperty('server.port' ) ?: '8080' def url = "http://localhost:${port}/actuator/health" try { def response = new URL(url).text println "Health check passed: ${response}" } catch (Exception e) { throw new GradleException("Health check failed: ${e.message}" ) } } }
⚡ 12. 常用命令与工具 12.1 基础构建命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ./gradlew build ./gradlew clean ./gradlew assemble ./gradlew check ./gradlew test ./gradlew jar ./gradlew :user-service:build ./gradlew :user-service:bootRun ./gradlew build --parallel ./gradlew build --continue ./gradlew dependencies ./gradlew dependencyInsight --dependency spring-core ./gradlew buildEnvironment ./gradlew properties
12.2 性能分析命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ./gradlew build --profile ./gradlew build --scan ./gradlew build --dry-run ./gradlew build --debug ./gradlew build --info ./gradlew build --stacktrace ./gradlew build --full-stacktrace ./gradlew build --build-cache ./gradlew cleanBuildCache
12.3 任务管理命令 1 2 3 4 5 6 7 8 9 10 11 12 13 ./gradlew tasks ./gradlew tasks --all ./gradlew :user-service:tasks ./gradlew myTask ./gradlew myTask --rerun-tasks ./gradlew myTask --offline ./gradlew myTask --dry-run ./gradlew help --task myTask
🔧 13. 故障排除与调试 13.1 常见问题解决 ❌ 问题1:构建缓存问题
1 2 3 4 5 6 7 ./gradlew clean build --no-build-cache ./gradlew cleanBuildCache ./gradlew myTask --info
❌ 问题2:依赖解析失败
1 2 3 4 5 6 7 ./gradlew dependencies --refresh-dependencies ./gradlew build --refresh-dependencies ./gradlew buildEnvironment
❌ 问题3:内存不足
1 2 3 4 5 6 7 org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g export GRADLE_OPTS="-Xmx4g" ./gradlew build
❌ 问题4:Daemon问题
1 2 3 4 5 ./gradlew --stop ./gradlew --no-daemon build ./gradlew --status
13.2 调试技巧 🔍 构建脚本调试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 println "Current project: ${project.name}" println "Java version: ${java.sourceCompatibility}" gradle.taskGraph.whenReady { taskGraph -> println "Tasks to execute: ${taskGraph.allTasks*.name}" } gradle.taskGraph.afterTask { task, taskState -> if (taskState.failure) { println "Task ${task.name} failed: ${taskState.failure}" } } gradle.projectsEvaluated { println "All projects evaluated" }
📊 性能分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class TimingPlugin implements Plugin <Project> { void apply(Project project) { project.gradle.addListener(new TaskExecutionTimeListener()) } } class TaskExecutionTimeListener implements TaskExecutionListener { private long startTime void beforeExecute(Task task) { startTime = System.currentTimeMillis() } void afterExecute(Task task, TaskState state) { long duration = System.currentTimeMillis() - startTime println "${task.path} took ${duration}ms" } }
🏆 14. 最佳实践总结 14.1 项目结构最佳实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 my-gradle-project/ ├── settings.gradle ├── build.gradle ├── gradle.properties ├── buildSrc/ │ ├── build.gradle │ └── src/main/groovy/ ├── gradle/ │ └── wrapper/ ├── common/ ├── services/ ├── infrastructure/ └── docs/
14.2 构建脚本最佳实践 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 plugins { } group = 'com.example' version = '1.0.0' repositories { } dependencies { } tasks.named('test' ) { } task customTask { }
14.3 性能优化最佳实践 1 2 3 4 5 6 org.gradle.daemon =true org.gradle.parallel =true org.gradle.configureondemand =true org.gradle.caching =true org.gradle.jvmargs =-Xmx4g -XX:MaxMetaspaceSize=1g
14.4 版本管理最佳实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 dependencyResolutionManagement { versionCatalogs { libs { library('spring-boot-starter-web' , 'org.springframework.boot' , 'spring-boot-starter-web' ).version('2.7.0' ) library('junit-jupiter' , 'org.junit.jupiter' , 'junit-jupiter' ).version('5.9.2' ) bundle('spring-boot' , ['spring-boot-starter-web' , 'spring-boot-starter-actuator' ]) } } } dependencies { implementation libs.spring.boot.starter.web testImplementation libs.junit.jupiter implementation libs.bundles.spring.boot }
📚 总结与进阶学习 🎯 学习成果检验 通过本手册的学习,您应该掌握:
✅ 基础知识
Gradle的核心概念和优势
DSL语法和构建脚本编写
任务系统和依赖管理
插件使用和配置
✅ 进阶技能
多项目构建管理
自定义插件开发
性能优化技巧
企业级应用实践
✅ 实战能力
能够设计和实现复杂的构建系统
解决常见的构建问题
优化构建性能
遵循最佳实践
🚀 进阶学习建议
深入学习Gradle内部机制
理解Gradle的构建生命周期
学习任务图和依赖解析机制
企业级实践
学习Gradle Enterprise的使用
掌握大型项目的构建优化
生态系统集成
学习与CI/CD系统的集成
了解与Docker、Kubernetes的结合
插件生态
探索丰富的Gradle插件生态
学习编写高质量的自定义插件
📖 推荐资源
🎉 文章总结
🎯 基础概念 :Gradle核心优势、安装配置、项目结构
📝 DSL语法 :Groovy/Kotlin DSL、构建脚本编写、语法特性
⚙️ 任务系统 :任务定义、依赖关系、输入输出管理
🔍 依赖管理 :配置类型、版本管理、冲突解决
🏗️ 多项目构建 :项目结构设计、配置管理、构建策略
🔌 插件开发 :自定义插件、任务类、扩展开发
⚡ 性能优化 :构建缓存、并行构建、增量构建
🎯 实战案例 :微服务项目、企业级应用、最佳实践
🌟 核心价值
现代化工具 :体验比Maven更快更灵活的构建方式
企业级实践 :适用于大型复杂项目的构建管理
性能导向 :充分利用Gradle的性能优势
生态丰富 :强大的插件生态系统支持