Gradle进阶与实战
# Gradle 进阶与实战
本文涵盖 Gradle 的进阶用法:自定义 Task、镜像加速、属性配置、构建缓存、Maven 迁移等实战内容,并结合 interview-guide 项目的真实代码讲解。
# 自定义 Task
# Task 的基本定义
// 方式一:register(推荐,延迟创建)
tasks.register('myTask') {
group = 'custom'
description = '自定义任务示例'
doLast {
println '执行自定义任务'
}
}
// 方式二:create(旧式,立即创建)
task myTask {
doLast {
println '执行自定义任务'
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
register是延迟创建,只有当 Task 被实际需要时才创建实例,性能更好。create已不推荐使用。
# Task 类型
Gradle 提供了多种内置 Task 类型,可以直接继承:
| Task 类型 | 说明 |
|---|---|
Copy | 文件复制 |
Delete | 文件删除 |
Exec | 执行外部命令 |
JavaExec | 执行 Java 程序 |
Test | 运行测试 |
Jar | 打包 JAR |
Zip / Tar | 打包压缩文件 |
# Copy Task 示例
tasks.register('copyConfig', Copy) {
from 'src/main/config'
into 'build/config'
include '*.properties'
exclude '*.bak'
}
2
3
4
5
6
# Exec Task 示例
tasks.register('runScript', Exec) {
workingDir = file('scripts')
commandLine 'sh', 'deploy.sh'
}
2
3
4
# 自定义 Test Task
interview-guide 项目注册了专门的测试 Task,只运行特定标签的测试:
tasks.register('ragEvaluation', Test) {
description = '运行 RAG 测评(需要 RUN_RAG_EVAL=true)'
group = 'verification'
testClassesDirs = sourceSets.test.output.classesDirs
classpath = sourceSets.test.runtimeClasspath
useJUnitPlatform {
includeTags 'rag-eval'
}
jvmArgs '--enable-native-access=ALL-UNNAMED'
systemProperty 'ragEval.reportDir', layout.buildDirectory.dir('reports/rag-eval').get().asFile.absolutePath
outputs.upToDateWhen { false }
}
2
3
4
5
6
7
8
9
10
11
12
关键配置说明:
| 配置项 | 说明 |
|---|---|
testClassesDirs | 测试类输出目录(复用主 test 的编译产物) |
classpath | 测试运行 classpath |
useJUnitPlatform { includeTags } | 只运行带指定标签的测试 |
systemProperty | 传入系统属性 |
outputs.upToDateWhen { false } | 禁用增量检查,每次都执行 |
这个 Task 复用了
sourceSets.test的编译产物,不需要重新编译测试代码,只是用不同的标签过滤来运行不同的测试子集。
# Task 依赖
tasks.register('taskA') {
doLast { println 'A' }
}
tasks.register('taskB') {
dependsOn 'taskA' // taskB 执行前先执行 taskA
doLast { println 'B' }
}
// 执行 gradlew taskB 会先执行 taskA
2
3
4
5
6
7
8
9
10
# Task 输入输出
声明 Task 的输入输出,Gradle 可以据此做增量构建:
tasks.register('processData') {
// 声明输入
inputs.file('src/main/data/input.txt')
// 声明输出
outputs.file('build/data/output.txt')
doLast {
def input = file('src/main/data/input.txt').text
file('build/data/output.txt').text = input.toUpperCase()
}
}
2
3
4
5
6
7
8
9
10
11
如果输入文件没变且输出文件已存在,Gradle 会标记 Task 为
UP-TO-DATE并跳过执行。
# 从 .env 文件加载环境变量
interview-guide 项目在多个 Task 中读取 .env 文件注入环境变量:
tasks.register('ragEvaluation', Test) {
// ...
def envFile = rootProject.file('.env')
if (envFile.exists()) {
envFile.eachLine { line ->
def trimmed = line.trim()
if (trimmed && !trimmed.startsWith('#') && trimmed.contains('=')) {
def (key, value) = trimmed.split('=', 2)
if (System.getenv(key) == null) {
environment key, value
}
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Gradle 进程默认不读取
.env文件,需要手动解析注入。这段代码会跳过注释行和空行,且不覆盖已有的系统环境变量。
# 镜像加速配置
国内使用 Gradle 最大的痛点是下载慢。需要配置三个层面的镜像:
# 1. Gradle 发行版镜像
在 gradle/wrapper/gradle-wrapper.properties 中配置:
# 腾讯云(首选)
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-9.6.1-bin.zip
# 阿里云(备选)
#distributionUrl=https\://mirrors.aliyun.com/gradle/gradle-9.6.1-bin.zip
2
3
4
5
# 2. 插件仓库镜像
在 settings.gradle 的 pluginManagement 中配置:
pluginManagement {
repositories {
maven { url = uri('https://maven.aliyun.com/repository/public/') }
maven { url = uri('https://maven.aliyun.com/repository/gradle-plugin/') }
maven { url = uri('https://maven.aliyun.com/repository/spring-plugin/') }
gradlePluginPortal()
}
}
2
3
4
5
6
7
8
# 3. 依赖仓库镜像
在 build.gradle 的 repositories 中配置:
repositories {
maven { url = uri('https://maven.aliyun.com/repository/public/') }
maven { url = uri('https://maven.aliyun.com/repository/spring/') }
mavenCentral()
maven { url = uri('https://repo.spring.io/milestone') }
}
2
3
4
5
6
# 常用国内镜像
| 镜像 | 地址 | 用途 |
|---|---|---|
| 阿里云公共仓库 | https://maven.aliyun.com/repository/public/ | 通用依赖 |
| 阿里云 Gradle 插件 | https://maven.aliyun.com/repository/gradle-plugin/ | Gradle 插件 |
| 阿里云 Spring | https://maven.aliyun.com/repository/spring/ | Spring 相关 |
| 阿里云 Spring 里程碑 | https://maven.aliyun.com/repository/spring-plugin/ | Spring 里程碑版本 |
| 腾讯云 Gradle | https://mirrors.cloud.tencent.com/gradle/ | Gradle 发行版 |
| 华为云 | https://mirrors.huaweicloud.com/repository/maven/public/ | 通用依赖 |
interview-guide 项目同时使用了腾讯云(Gradle 发行版)和阿里云(依赖和插件),覆盖了所有下载场景。
# gradle.properties 配置
gradle.properties 是 Gradle 的属性配置文件,可以放在项目根目录或 ~/.gradle/ 全局目录。
# 项目级配置
interview-guide 项目的 gradle.properties:
# 指定 JDK 版本路径
org.gradle.java.home=D:\\software\\java\\jdk\\jdk25
# 指定编码格式,避免控制台中文乱码
org.gradle.jvmargs=-Dfile.encoding=UTF-8
2
3
4
# 常用配置汇总
# ===== JVM 配置 =====
org.gradle.java.home=D:\\software\\java\\jdk\\jdk25
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8
# ===== 构建加速 =====
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configureondemand=true
# ===== 超时配置 =====
org.gradle.internal.http.connectionTimeout=120000
org.gradle.internal.http.socketTimeout=120000
2
3
4
5
6
7
8
9
10
11
12
13
# 内置属性一览
| 属性 | 说明 | 默认值 |
|---|---|---|
org.gradle.java.home | 构建使用的 JDK 路径 | 系统默认 |
org.gradle.jvmargs | Daemon JVM 参数 | - |
org.gradle.daemon | 是否启用 Daemon | true |
org.gradle.parallel | 是否并行构建 | false |
org.gradle.caching | 是否启用构建缓存 | false |
org.gradle.configureondemand | 按需配置 | false |
org.gradle.workers.max | 最大 Worker 数 | CPU 核数 |
org.gradle.logging.level | 日志级别 | - |
# 自定义属性
# gradle.properties
springProfilesActive=dev
2
// build.gradle 中使用
def profile = project.findProperty('springProfilesActive') ?: 'dev'
2
# 构建缓存与增量构建
# 增量构建
Gradle 的增量构建是自动的:每个 Task 声明了输入和输出,如果输入没变且输出已存在,Task 会被标记为 UP-TO-DATE 并跳过。
# 第一次构建
gradlew build
# > Task :compileJava
# > Task :test
# 第二次构建(无变更)
gradlew build
# > Task :compileJava UP-TO-DATE
# > Task :test UP-TO-DATE
2
3
4
5
6
7
8
9
# 构建缓存
构建缓存可以跨项目、跨机器复用 Task 输出:
# gradle.properties
org.gradle.caching=true
2
# 命令行启用
gradlew build --build-cache
2
# 本地构建缓存
默认存储在 ~/.gradle/caches/build-cache-1/:
# gradle.properties
org.gradle.caching=true
# 自定义缓存目录
org.gradle.cache.location=D:/gradle-cache
2
3
4
# 远程构建缓存
CI 环境可以配置远程构建缓存,让所有开发者共享缓存:
// settings.gradle
buildCache {
local {
enabled = true
}
remote(HttpBuildCache) {
url = 'https://gradle-cache.example.com/cache/'
credentials {
username = 'cache-user'
password = 'cache-password'
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 编码问题解决
# 控制台中文乱码
在 gradle.properties 中配置:
org.gradle.jvmargs=-Dfile.encoding=UTF-8
# 编译编码
在 build.gradle 中配置:
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
options.release = 25
}
2
3
4
# bootRun 编码
interview-guide 项目在 bootRun 中配置了完整的 JVM 编码参数:
tasks.named('bootRun') {
jvmArgs = [
'-Dfile.encoding=UTF-8',
'-Dconsole.encoding=UTF-8',
'-Dstdout.encoding=UTF-8',
'-Dstderr.encoding=UTF-8',
'--enable-native-access=ALL-UNNAMED'
]
}
2
3
4
5
6
7
8
9
JDK 18+ 默认使用 UTF-8,但显式配置可以避免不同环境下的编码不一致问题。
# init 脚本
Gradle 支持在 ~/.gradle/init.d/ 或 ~/.gradle/init.gradle 中放置初始化脚本,对所有项目生效。
# 全局镜像配置
~/.gradle/init.gradle:
allprojects {
repositories {
def aliyunRepos = 'https://maven.aliyun.com/repository/public/'
def aliyunPlugin = 'https://maven.aliyun.com/repository/gradle-plugin/'
all { ArtifactRepository repo ->
if (repo instanceof MavenArtifactRepository) {
def url = repo.url.toString()
if (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com')) {
repo.url = aliyunRepos
}
if (url.startsWith('https://plugins.gradle.org/m2')) {
repo.url = aliyunPlugin
}
}
}
maven { url = uri(aliyunRepos) }
maven { url = uri(aliyunPlugin) }
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这段脚本会自动将 Maven 中央仓库和 Gradle 插件门户的请求重定向到阿里云镜像,对所有项目生效。
# Maven 迁移到 Gradle
# 自动迁移
Gradle 提供了从 Maven 自动迁移的命令:
# 在 Maven 项目根目录执行
gradle init
2
Gradle 会分析 pom.xml,自动生成 build.gradle、settings.gradle 和 libs.versions.toml。
自动迁移能处理大部分依赖和插件,但自定义插件配置、Profile 等需要手动调整。
# 手动迁移对照表
| Maven 配置 | Gradle 配置 |
|---|---|
<groupId> | group = '...' |
<artifactId> | 项目名(settings.gradle 中定义) |
<version> | version = '...' |
<packaging>jar</packaging> | id 'java' 插件 |
<packaging>war</packaging> | id 'war' 插件 |
<properties> | ext { } 或 gradle.properties |
<dependencies> | dependencies { } |
<dependencyManagement> | Version Catalog 或 platform() |
<build><plugins> | plugins { } |
<profiles> | if (project.hasProperty('xxx')) 或 SourceSet |
<modules> | include() |
| 父 POM 继承 | subprojects {} 或 convention plugin |
# scope 迁移对照
| Maven scope | Gradle 配置项 |
|---|---|
compile | implementation(或 api) |
provided | compileOnly |
runtime | runtimeOnly |
test | testImplementation |
import(BOM) | platform() |
# Profile 迁移
Maven 的 Profile 在 Gradle 中用条件逻辑替代:
// Maven Profile → Gradle 条件配置
def profile = project.findProperty('env') ?: 'dev'
if (profile == 'prod') {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
tasks.named('bootRun') {
systemProperty 'spring.profiles.active', 'prod'
}
} else {
dependencies {
implementation 'org.springframework.boot:spring-boot-devtools'
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 常见问题
# 1. 依赖下载失败
现象:Could not resolve xxx
解决:
- 检查
repositories是否配置了正确的镜像 - 尝试
gradlew build --refresh-dependencies强制刷新 - 检查网络连接和代理配置
# 2. Lombok 不生效
现象:编译报错找不到 getter/setter 方法
解决:确保同时配置 compileOnly 和 annotationProcessor:
dependencies {
compileOnly libs.lombok
annotationProcessor libs.lombok
}
2
3
4
# 3. MapStruct + Lombok 冲突
现象:MapStruct 生成的代码找不到 Lombok 生成的方法
解决:确保 Lombok 在 MapStruct 之前配置,并添加 binding:
dependencies {
compileOnly libs.lombok
annotationProcessor libs.lombok
implementation "org.mapstruct:mapstruct:${libs.versions.mapstruct.get()}"
annotationProcessor "org.mapstruct:mapstruct-processor:${libs.versions.mapstruct.get()}"
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
}
2
3
4
5
6
7
8
# 4. 构建慢
解决:
- 启用 Daemon、并行、缓存:
gradle.properties配置 - 使用
--configure-on-demand - 检查是否有耗时操作在配置阶段执行(应移到
doLast) - 使用
--profile分析构建耗时
# 5. 版本冲突
现象:Conflict found for ...
解决:
// 查看依赖树定位冲突
gradlew dependencies --configuration runtimeClasspath
// 强制指定版本
configurations.all {
resolutionStrategy {
force 'org.slf4j:slf4j-api:2.0.9'
}
}
2
3
4
5
6
7
8
9
# interview-guide 项目配置总结
interview-guide 项目的 Gradle 配置涵盖了本文大部分内容:
| 配置文件 | 作用 |
|---|---|
settings.gradle | 插件仓库镜像、工具链插件、项目名称、子项目声明 |
gradle.properties | JDK 路径、JVM 编码参数 |
gradle/libs.versions.toml | Version Catalog,集中管理所有依赖版本 |
gradle/wrapper/gradle-wrapper.properties | Gradle 发行版镜像(腾讯云) |
app/build.gradle | 插件、依赖、Toolchain、编码、自定义 Task、bootRun 配置 |
关键配置亮点:
- 镜像加速:腾讯云(Gradle 发行版)+ 阿里云(依赖和插件)
- Version Catalog:所有版本集中在
libs.versions.toml - Toolchain:自动使用 Java 25
- 自定义 Task:
ragEvaluation、voiceContextEvaluation按标签运行不同测试 - .env 注入:
bootRun和测试 Task 自动加载.env文件 - 编码配置:全局 UTF-8,避免中文乱码