Gradle 入门与进阶
Tips
本教程全面介绍Gradle构建工具的使用方法,从基础配置到高级应用,适用于Gradle 7.0及更高版本。
1. Gradle简介
Gradle是一个开源的自动化构建工具,它结合了Ant和Maven的优点,提供了更灵活、更高效的构建方式。Gradle使用Groovy或Kotlin DSL作为构建脚本语言,支持增量构建,并具有出色的多项目构建能力。
1.1 Gradle的主要特点
- 声明式构建:使用Groovy或Kotlin DSL声明式构建脚本
- 高度可定制:灵活的API允许自定义构建逻辑
- 增量构建:智能跳过已完成的任务,提高构建速度
- 构建缓存:缓存构建结果,减少重复工作
- 多项目支持:强大的多项目构建能力
- 插件生态系统:丰富的插件扩展功能
- 依赖管理:高级依赖管理功能
1.2 与其他构建工具的对比
特性 | Gradle | Maven | Ant |
---|---|---|---|
构建语言 | Groovy/Kotlin DSL | XML | XML |
可扩展性 | 很高 | 中等 | 很高 |
约定优于配置 | 支持但可选 | 强制 | 不支持 |
依赖管理 | 强大而灵活 | 内置但固定 | 需要扩展 |
构建性能 | 很高(增量构建) | 中等 | 低 |
学习曲线 | 陡峭 | 中等 | 中等 |
生态系统 | 快速增长 | 成熟广泛 | 成熟 |
2. 安装与配置
2.1 安装Gradle
Windows安装:
- 下载Gradle二进制包:Gradle官方下载
- 解压到指定目录,如
C:\Program Files\Gradle
- 设置环境变量:
- 新建
GRADLE_HOME
,值为Gradle安装目录 - 将
%GRADLE_HOME%\bin
添加到PATH变量
- 新建
macOS安装:
# 使用Homebrew
brew install gradle
# 验证安装
gradle -v
Linux安装:
# Ubuntu/Debian
sudo apt install gradle
# SDKMAN方式(推荐)
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install gradle
# 验证安装
gradle -v
2.2 Gradle Wrapper
Gradle Wrapper是推荐的使用方式,它允许在没有安装Gradle的环境中运行构建:
# 生成Wrapper文件
gradle wrapper --gradle-version=7.6
# 使用Wrapper运行构建
./gradlew build # Linux/macOS
gradlew.bat build # Windows
Wrapper文件包括:
gradlew
/gradlew.bat
:启动脚本gradle/wrapper/gradle-wrapper.jar
:Wrapper JARgradle/wrapper/gradle-wrapper.properties
:配置文件
2.3 IDE集成
IntelliJ IDEA:内置Gradle支持,导入Gradle项目时自动识别
Eclipse:安装Buildship插件(Eclipse Marketplace)
Visual Studio Code:安装Gradle插件
3. Gradle基本概念
3.1 项目和任务
Gradle构建的两个基本概念:
- 项目(Project):代表要构建的软件
- 任务(Task):项目构建过程中的原子操作
每个Gradle构建至少包含一个项目,每个项目包含一个或多个任务。
3.2 构建生命周期
Gradle构建生命周期分为三个阶段:
- 初始化阶段:确定参与构建的项目
- 配置阶段:解析构建脚本,创建任务图
- 执行阶段:根据任务依赖顺序执行任务
3.3 构建脚本文件
Gradle项目通常包含以下文件:
build.gradle(.kts)
:项目构建脚本settings.gradle(.kts)
:多项目构建设置gradle.properties
:构建属性配置buildSrc/
:构建逻辑源代码目录
4. 构建脚本基础
4.1 Groovy DSL与Kotlin DSL
Gradle支持两种DSL编写构建脚本:
Groovy DSL (build.gradle):
plugins {
id 'java'
}
group = 'com.jdwa'
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter:2.7.0'
testImplementation 'junit:junit:4.13.2'
}
Kotlin DSL (build.gradle.kts):
plugins {
java
}
group = "com.jdwa"
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter:2.7.0")
testImplementation("junit:junit:4.13.2")
}
4.2 项目属性
定义和使用项目属性:
// 在build.gradle.kts中
val projectVersion by extra("1.0.0")
val javaVersion = JavaVersion.VERSION_17
// 在gradle.properties中
org.gradle.caching=true
org.gradle.parallel=true
kotlin.code.style=official
访问属性:
println("Project version: ${project.extra["projectVersion"]}")
println("Java version: $javaVersion")
println("Parallel execution: ${project.findProperty("org.gradle.parallel")}")
4.3 settings.gradle文件
settings.gradle(.kts)定义多项目构建结构:
// settings.gradle.kts
rootProject.name = "jdwa-multi-project"
include("app", "core", "util")
// 自定义项目路径
project(":app").projectDir = file("applications/app")
5. 任务(Task)
5.1 任务定义
基本任务定义:
// Kotlin DSL
tasks.register("hello") {
description = "Prints hello world"
group = "Custom"
doLast {
println("Hello, World!")
}
}
// Groovy DSL
task hello {
description 'Prints hello world'
group 'Custom'
doLast {
println "Hello, World!"
}
}
5.2 任务类型
使用预定义的任务类型:
// Kotlin DSL
tasks.register<Copy>("copyDocs") {
from("src/docs")
into("build/docs")
include("**/*.md", "**/*.txt")
exclude("drafts/**")
}
tasks.register<Zip>("packageDocs") {
archiveFileName.set("docs.zip")
destinationDirectory.set(file("$buildDir/dist"))
from("$buildDir/docs")
}
5.3 任务依赖
定义任务间的依赖关系:
// 方式1:依赖声明
tasks.register("taskA") {
dependsOn("taskB", "taskC")
doLast {
println("Task A executed")
}
}
// 方式2:创建时依赖
tasks.register("taskD") {
doLast {
println("Task D executed")
}
}
tasks.named("taskA") {
dependsOn(tasks.named("taskD"))
}
// 方式3:延迟依赖
tasks.register("taskE") {
dependsOn(provider { tasks.filter { it.name.startsWith("prepare") } })
doLast {
println("Task E executed after all prepare tasks")
}
}
5.4 任务排序
控制任务执行顺序(不是依赖关系):
// 确保taskA在taskB之前执行,即使没有依赖关系
tasks.named("taskA") {
mustRunAfter("taskB")
}
// taskC应该在taskD之前执行,但不强制
tasks.named("taskC") {
shouldRunAfter("taskD")
}
// 确定finalizer任务
tasks.named("taskE") {
finalizedBy("cleanup")
}
6. 依赖管理
6.1 配置仓库
配置依赖仓库:
repositories {
// Maven中央仓库
mavenCentral()
// JCenter仓库
jcenter()
// 谷歌仓库
google()
// 自定义Maven仓库
maven {
url = uri("https://maven.aliyun.com/repository/public")
name = "Aliyun"
}
// 本地Maven仓库
mavenLocal()
// Ivy仓库
ivy {
url = uri("https://ivy.example.org")
}
}
6.2 依赖配置
添加依赖:
dependencies {
// 编译时依赖
implementation("org.springframework:spring-core:5.3.20")
// 仅API依赖
api("org.apache.commons:commons-lang3:3.12.0")
// 仅编译时依赖
compileOnly("org.projectlombok:lombok:1.18.24")
// 注解处理器
annotationProcessor("org.projectlombok:lombok:1.18.24")
// 测试依赖
testImplementation("junit:junit:4.13.2")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// 特定配置依赖
"developmentOnly"("org.springframework.boot:spring-boot-devtools")
}
6.3 依赖版本管理
依赖约束:
dependencies {
// 声明约束
constraints {
implementation("org.apache.logging.log4j:log4j-core") {
version { strictly("2.17.1") }
because("Security vulnerability in earlier versions")
}
}
// 使用约束的依赖
implementation("org.apache.logging.log4j:log4j-core")
}
版本目录:
// 在settings.gradle.kts中
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
version("spring", "5.3.20")
version("junit", "5.8.2")
library("spring-core", "org.springframework", "spring-core").versionRef("spring")
library("spring-context", "org.springframework", "spring-context").versionRef("spring")
library("junit-api", "org.junit.jupiter", "junit-jupiter-api").versionRef("junit")
bundle("spring", listOf("spring-core", "spring-context"))
bundle("testing", listOf("junit-api"))
}
}
}
// 在build.gradle.kts中使用
dependencies {
implementation(libs.spring.core)
implementation(libs.bundles.spring)
testImplementation(libs.bundles.testing)
}
6.4 依赖解析冲突
处理依赖冲突:
configurations.all {
// 解决策略:失败
resolutionStrategy.failOnVersionConflict()
// 或解决策略:强制使用特定版本
resolutionStrategy.force(
"org.slf4j:slf4j-api:1.7.36",
"com.google.guava:guava:31.1-jre"
)
// 缓存动态版本的时间
resolutionStrategy.cacheDynamicVersionsFor(10, "minutes")
// 缓存变化模块的时间
resolutionStrategy.cacheChangingModulesFor(4, "hours")
}
7. 插件系统
7.1 应用插件
应用核心插件:
plugins {
java
`java-library`
application
`maven-publish`
}
应用社区插件:
plugins {
id("org.springframework.boot") version "2.7.0"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
id("com.github.johnrengelman.shadow") version "7.1.2"
}
7.2 自定义任务插件
在构建脚本中创建简单插件:
// 定义插件
class GreetingPlugin : Plugin<Project> {
override fun apply(project: Project) {
// 添加扩展
val extension = project.extensions.create<GreetingExtension>("greeting")
// 创建任务
project.tasks.register("hello") {
description = "Prints a greeting message"
group = "Custom"
doLast {
println("${extension.message ?: "Hello"}, ${extension.target ?: "World"}!")
}
}
}
}
// 定义扩展
open class GreetingExtension {
var message: String? = null
var target: String? = null
}
// 应用插件
apply<GreetingPlugin>()
// 配置插件
configure<GreetingExtension> {
message = "Hi"
target = "Gradle"
}
7.3 发布自定义插件
在buildSrc
目录或独立项目中创建插件:
// buildSrc/build.gradle.kts
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
// buildSrc/src/main/kotlin/com.jdwa.gradle/JdwaPlugin.kt
package com.jdwa.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
class JdwaPlugin : Plugin<Project> {
override fun apply(project: Project) {
// 插件实现
}
}
// 在主项目build.gradle.kts中应用
plugins {
id("com.jdwa.gradle")
}
7.4 常用插件介绍
- Java插件:编译Java源代码、运行测试、创建JAR
- 应用插件:创建可执行的JVM应用
- Spring Boot插件:构建Spring Boot应用
- Shadow插件:创建包含所有依赖的fat JAR
- Kotlin插件:支持Kotlin语言
- Docker插件:构建Docker镜像
- JaCoCo插件:代码覆盖率报告
8. 多项目构建
8.1 创建多项目结构
rootProject/
├── settings.gradle.kts
├── build.gradle.kts
├── app/
│ └── build.gradle.kts
├── core/
│ └── build.gradle.kts
└── util/
└── build.gradle.kts
settings.gradle.kts:
rootProject.name = "jdwa-multi-project"
include("app", "core", "util")
8.2 配置所有项目
根项目build.gradle.kts:
// 所有项目通用配置
allprojects {
group = "com.jdwa"
version = "1.0.0"
repositories {
mavenCentral()
}
}
// 仅子项目配置
subprojects {
apply(plugin = "java")
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
tasks.withType<Test> {
useJUnitPlatform()
}
}
8.3 子项目依赖
core/build.gradle.kts:
plugins {
`java-library`
}
dependencies {
api("org.apache.commons:commons-lang3:3.12.0")
implementation("com.google.guava:guava:31.1-jre")
}
app/build.gradle.kts:
plugins {
application
}
application {
mainClass.set("com.jdwa.app.Main")
}
dependencies {
implementation(project(":core"))
implementation(project(":util"))
}
8.4 组合构建
复合构建允许不同的Gradle项目一起构建:
settings.gradle.kts:
includeBuild("../other-project")
依赖替换:
dependencies {
implementation("org.example:other-project:1.0.0")
}
9. 构建性能优化
9.1 开启并行构建
# gradle.properties
org.gradle.parallel=true
或命令行:
./gradlew build --parallel
9.2 构建缓存
# gradle.properties
org.gradle.caching=true
或命令行:
./gradlew build --build-cache
9.3 增量编译
Gradle默认支持增量编译,确保任务正确声明输入和输出:
tasks.register<ProcessResources>("processConfig") {
// 声明输入文件
from(file("src/config"))
// 声明输出目录
into("$buildDir/config")
// 声明属性输入
inputs.property("version", project.version)
// 过滤文件内容
filter { line -> line.replace("@VERSION@", "${project.version}") }
}
9.4 配置Gradle守护进程
# gradle.properties
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError
10. 高级特性
10.1 Gradle测试套件
设置测试套件:
testing {
suites {
// 默认测试套件
val test by getting(JvmTestSuite::class) {
useJUnitJupiter()
}
// 集成测试套件
val integrationTest by registering(JvmTestSuite::class) {
dependencies {
implementation(project())
implementation("org.testcontainers:testcontainers")
}
targets {
all {
testTask.configure {
shouldRunAfter(test)
}
}
}
}
}
}
tasks.named("check") {
dependsOn(testing.suites.named("integrationTest"))
}
10.2 自定义Task类型
创建自定义任务类型:
// 定义任务类型
abstract class CountLinesTask : DefaultTask() {
@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val sources: ConfigurableFileCollection
@get:OutputFile
abstract val outputFile: RegularFileProperty
@TaskAction
fun count() {
val counts = mutableMapOf<String, Int>()
sources.forEach { file ->
if (file.isFile) {
val extension = file.extension
val lineCount = file.readLines().size
counts[extension] = (counts[extension] ?: 0) + lineCount
}
}
val output = counts.entries.joinToString("\n") {
"${it.key}: ${it.value} lines"
}
outputFile.get().asFile.writeText(output)
}
}
// 使用自定义任务类型
tasks.register<CountLinesTask>("countLines") {
sources.from(fileTree("src/main").include("**/*.*"))
outputFile.set(file("$buildDir/reports/line-count.txt"))
}
10.3 发布构件
发布Maven构件:
plugins {
`maven-publish`
signing
}
// 配置发布
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
pom {
name.set("JDWA Library")
description.set("A sample library for demonstration")
url.set("https://github.com/AAASS554/jdwa-library")
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
developers {
developer {
id.set("jdwa")
name.set("记得晚安")
email.set("1412800823@qq.com")
}
}
scm {
connection.set("scm:git:git://github.com/AAASS554/jdwa-library.git")
developerConnection.set("scm:git:ssh://github.com/AAASS554/jdwa-library.git")
url.set("https://github.com/AAASS554/jdwa-library")
}
}
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/AAASS554/jdwa-library")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}
// 签名配置
signing {
sign(publishing.publications["mavenJava"])
}
10.4 自定义Gradle插件库
创建公司内部的插件库:
// settings.gradle.kts
pluginManagement {
repositories {
gradlePluginPortal()
maven {
url = uri("https://maven.company.com/plugins")
credentials {
username = providers.gradleProperty("companyRepoUser").orNull
password = providers.gradleProperty("companyRepoPassword").orNull
}
}
}
plugins {
id("com.company.java") version "1.0.0"
id("com.company.quality") version "1.2.0"
}
}
11. 最佳实践
11.1 项目结构
标准Java项目结构:
project/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle.properties
├── gradle/
│ └── wrapper/
├── src/
│ ├── main/
│ │ ├── java/
│ │ ├── kotlin/
│ │ └── resources/
│ └── test/
│ ├── java/
│ ├── kotlin/
│ └── resources/
├── buildSrc/ # 构建逻辑
└── config/ # 项目配置
11.2 配置管理
分离配置逻辑:
project/
├── gradle/
│ ├── libs.versions.toml # 依赖版本目录
│ ├── build-logic.gradle # 构建逻辑
│ └── publishing.gradle # 发布配置
build.gradle.kts:
// 应用共享配置
apply(from = "gradle/build-logic.gradle")
apply(from = "gradle/publishing.gradle")
11.3 持续集成配置
GitHub Actions配置:
# .github/workflows/gradle.yml
name: Gradle Build
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
with:
gradle-version: wrapper
- name: Build with Gradle
run: ./gradlew build
- name: Run tests
run: ./gradlew test
- name: Publish Test Report
uses: mikepenz/action-junit-report@v3
if: always()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
11.4 常见问题解决
依赖解析问题:
# 查看依赖树 ./gradlew app:dependencies # 查看依赖洞察 ./gradlew app:dependencyInsight --dependency commons-io:commons-io
任务配置问题:
# 使用--scan生成构建扫描报告 ./gradlew build --scan # 使用--info查看详细日志 ./gradlew build --info
性能问题:
# 生成性能报告 ./gradlew build --profile # 使用构建扫描分析性能 ./gradlew build --scan
结语
Gradle是一个强大而灵活的构建工具,掌握它需要时间和实践。本教程涵盖了Gradle的基本用法到高级特性,帮助你更好地理解和使用Gradle。随着项目的增长和复杂性的提高,Gradle的优势会越来越明显,特别是在构建性能和可维护性方面。