一、Gradle

Gradle 与 Maven 的区别可以看这篇 文章

日常作为简单的依赖管理使用哪个都是没有问题的。有句话说的好:高端玩家选择自定义设置,普通玩家选择默认配置 😄 高级功能不一定使用。用的多了其实大概率更喜欢 gradle,它比较简单、清晰。

不过另一方面,Gradle 社区更新、更换 API 很勤快,也许上个版本还在用的 API,等更新版本后就幸运的看到了中国红!所以大家对 Maven 的版本要求一点儿也不严格,但是对于 Gradle,emmmm,这个得看你们的依赖脚本用了什么 API。

本文示例全部使用 kts 的写法(Gradle Version >= 7),也就是 kotlin 式的语法,体验比 Groovy 棒多啦!推荐可以看一下 B 站霍老师的的视频:

二、配置

Gradle 的配置分为两种,一种是本地安装的方式,就和本地安装的 Maven 一样;另一种则是直接配置一个环境变量。这 两种方式二选一 就好。

不过浪子要说的是,对于使用 JetBrains IDEA 早期版本(即 2023.2 以下)的用户来说,是否在本地安装 Gradle 并无太大区别。IDEA 的早期版本对本地的 Gradle 支持并不友好。在没有下载某个版本的前提下,无论是新建项目还是 clone 的已有项目,只要本地的默认目录没有该版本,每次都需要下载 gradle/wrapper/gradle-wrapper.properties 文件中定义的 Gradle 版本。且由于该文件只定义了二进制(bin)文件,如果后面有用到 doc 的功能,还需要额外下载 doc,无疑是慢上加慢。(默认的 url 分发地址,大概在 2023 年 9 月份开始,官网的下载速度就不行了,之前飞快,现在只能找找国内镜像)

而且,旧版的 IDEA 想要配置本地的 Gradle 必须要在构建的时候中止然后去设置里修改,很麻烦。

基于上述原因,对于早期版本的用户,浪子推荐设置 GRADLE_USER_HOME 环境变量,该变量不需要扔到 Path 里,只需要配置一个存储空间较大的路径,后面在使用 IDE 的时候,如果自动下载,那么所有版本的 gradle 安装包、依赖都会下载到此目录。结构如下(使用后就有了,刚开始是个空目录):

1
2
3
4
5
6
7
8
├── caches              # 依赖包
├── daemon # 守护进程运行日志以及注册的二进制文件(wrapper/)
├── init.gradle.kts # 初始化脚本
├── jdks #
├── kotlin-profile # 空的,看名字应该是 Kotlin 的支持吧
├── native # 本机 dll 文件
├── notifications # 不知道干嘛的
└── wrapper # 下载的 Gradle 二进制文件

如果想要本地安装,那么强烈推荐使用最新版的 IDEA(2023.3 ~ latest),社区版也是 OK 的!!!本地安装 Gradle 的作用终于显现出来啦!😉如果遇到官网打不开或者是下载过慢的情况,可以移步 腾讯 Gradle 镜像站 下载。

之后我们就可以配置依赖下载的镜像源了,镜像源地址也是使用腾讯的。当然这里是否使用根据自己的需要随时修改。这段代码来自于 B 站霍老师 的一个 视频 中的 gist(访问需要魔法),浪子自己手打的,累啊。。。Gradle Version > 6.8 时可用:

init.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
fun RepositoryHandler.enableMirror() {
all {
if (this is MavenArtifactRepository) {
val originUrl = this.url.toString().removeSuffix("/")
urlMappings[originUrl]?.let {
logger.lifecycle("Repository[$url] is mirrored to $it")
this.setUrl(it)
}
}
}
}

val urlMappings = mapOf(
"https://repo.maven.apache.org/maven2" to "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/",
"https://dl.google.com/dl/android/maven2" to "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/",
"https://plugins.gradle.org/m2" to "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/"
)

gradle.allprojects {
buildscript {
repositories.enableMirror()
}
repositories.enableMirror()
}

gradle.beforeSettings {
pluginManagement.repositories.enableMirror()
dependencyResolutionManagement.repositories.enableMirror()
}

如果熟悉 Kotlin,上面的内容很好理解,部分 API 是 Gradle 的,不用深入,领会就行。这里说一下:就是定义了一个 map,键为常见的 maven 源,值为国内的镜像源。若在下载依赖时如果匹配到 https://repo.maven.apache.org/maven2https://dl.google.com/dl/android/maven2https://plugins.gradle.org/m2 三个 Maven 坐标仓库中的依赖,通过 map 的 get(key) 方式获取到国内镜像地址然后设置到 gradle 构建工具里,实际下载使用镜像地址。此配置是全局生效的,不论是新建还是 clone 的已有项目。

推荐一个备用源(强烈推荐):https://nexus.kuku.me/repository/maven-public

该备用源是一位大佬自建的镜像仓库,推荐备用源是因为腾讯的有时候会断开,浪子也不清楚,可能偶尔维护的时候正好被我碰上了。

脚本路径

若本地安装了 Gradle,上面的脚本就放在本地安装的目录中;若本地未安装,放在配置的环境变量的目录中;如果前面两项都不满足,那么放在默认的路径:~/.gradle

若本地安装且配置了环境变量,命令行才可以使用 gradle;未安装只能在项目路径下使用 ./gradlew 命令(wrapper 会自动调用守护进程)。

哦,对了,提一下本文和 Gradle 官网 提到的几个环境变量。

  • GRADLE_HOME 自己本机安装的 Gradle 目录;
  • GRADLE_USER_HOME:自定义下载依赖的存放的路径,包括 wrapper/gradle/ 下定义的各种版本的 Gradle 及其下载的依赖。在 GRADLE_USER_HOME 变量缺失的时候,默认的位置为 ~/.gradle/

Gradle 是如何查找并使用本地的配置呢?

1
2
3
4
5
6
7
8
9
10
11
12
# Gradle 查找下载配置的顺序 * 代表可以为任意名称
~/.gradle/init.gradle
~/.gradle/init.d/*.gradle
GRADLE_HOME/init.d/*.gradle
GRADLE_USER_HOME/init.gradle
GRADLE_USER_HOME/init.d/*.gradle

# Gradle 查找依赖的顺序
# M2_HOME 是 Maven 的安装路径环境变量
~/.m2/settings.xml
M2_HOME/conf/settings.xml
~/.m2/repository

三、几个重要文件

单模块很简单,本文就不演示了。这里使用多模块项目作为一个小示例:

1
2
3
4
5
6
7
8
9
|-- Project
|-- sub-project-1
|-- src
|-- build.gradle.kts
|-- sub-project-2
|-- src
|-- build.gradle.kts
|-- settings.gradle.kts
|-- gradle.properties

1. settings.gradle.kts

settings.gradle.kts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 项目根文件夹名称
rootProject.name = "Project"

// 包含的子模块,下面两种写法二选一
// 可以交叉使用,但是浪子更推荐第二种写法
// 冒号表示相对路径;
// 也支持省略冒号的方式,若省略则被解释为相对于 settings.gradle.kts 文件所在目录的路径
// 方式一:
include(":sub-project-1", ":sub-project-1", ":module3", ":module4")
// 方式二:
include(":sub-project-1")
include(":sub-project-2")

// 还可以定制其它插件、管理依赖、版本等等,欲知详情,使用 idea 建立一个 quarkus 项目看看!

2. build.gradle.kts

该文件是我们最常见、常改的文件。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 项目使用插件
plugins {

}

// 基本信息
group = "com.code"
version = "1.0-SNAPSHOT"

// Java 版本
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}

// 对所有项目生效的配置
allprojects {

// 应用于所有项目的插件
apply {
plugin("插件名称")
}

repositories {
// 本地仓库
mavenLocal()
// 腾讯云仓库
maven("https://mirrors.cloud.tencent.com/nexus/repository/maven-public/")
// 默认不允许使用 http 下载,如果项目中需要从 http 下载依赖,打开下面的设置
// maven {
// url = uri("http://mirrors.cloud.tencent.com/nexus/repository/maven-public/")
// isAllowInsecureProtocol = true
// }
}

// 所有项目引入依赖
dependencies {
testImplementation "org.springframework.boot:spring-boot-starter-test"
}

// other task and config
}

// 只对子项目生效的配置
subprojects {
// 和 allprojects 的配置相同
}

// 设置编译器的字符集,以便能够正确地处理文件中的 Unicode 字符。
// 添加 JVM 参数
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
}

3. gradle.properties

该文件可以声明环境变量,进而覆盖 gradle 的默认配置。也可以在这里定义、维护版本号,总之这里的内容可以在被上面两个文件引用。

忽然发现部分初学者可能不太会使用 gradle 的几个配置(环境变量)。这里给一个简单的例子,开启这几个选项会让你明显感受到 gradle 的速度有一定的提升:

1
2
3
4
5
6
# 启用守护进程
org.gradle.daemon=true
# 使用并行构建
org.gradle.parallel=true
# 开启构建缓存
org.gradle.caching=true

四、Gradle scope

在Gradle中,有几种不同的依赖范围,它们定义了依赖在不同阶段的行为和可见性。以下是一些常见的依赖范围:

  1. api

    • 在新的Android插件和一些非Android项目中,推荐使用 api 替代 compile
    • api 范围的依赖在编译和运行时都是可用的,并且会被传递到依赖此模块的其他模块。
    • 这意味着,当你在某个模块中使用 api 来声明一个依赖时,这个依赖会同时被编译和打包到该模块的输出,并且任何依赖于这个模块的其他模块也将能够访问到这个依赖。
  2. implementation

    • implementation 范围的依赖在编译和运行时对当前模块是可用的,但在编译依赖此模块的其他模块时不可见。
    • 这意味着,如果你在一个模块中使用 implementation 依赖了一个库,那么其他依赖这个模块的模块需要自己再次声明对这个库的依赖。
  3. runtimeOnly(或runtime):

    • runtimeOnly 范围的依赖只在运行时是必需的,编译时不需要。
    • 这种依赖通常用于那些只需要在运行时加载的库,如JDBC驱动、日志框架的配置文件等。
  4. testImplementation

    • testImplementation 范围的依赖只在编译和运行测试代码时需要,不会影响主代码的编译和运行。
    • 这种依赖通常用于测试框架和相关的库。
  5. testRuntimeOnly

    • testRuntimeOnly 范围的依赖只在运行测试时需要,编译测试代码时不需要。
    • 这种依赖通常用于那些只在测试环境中使用的资源或库。

只有使用 java-library 才可以使用 apijava-library 插件是 java 插件的升级,它支持 java 插件的所有功能,并引入了额外的新功能。

五、Version Catalog

Gradle 7.x 引入了 version catalog 功能预览,gradle 8 默认启用(读取项目目录下的 gradle/libs.versions.toml),对于 Gradle 多模块需要依赖共享的项目非常好用。version-catalog 方式引入的依赖也是惰性的,即在文件中声明的依赖如果没有项目引入,则不会进行下载。

个人不是很喜欢 extra 和 buildSrc 的方式,当然,如果使用 kts 可以在文件里直接 val xxxVersion = "version" 更香。

在项目根目录的 gradle/ 目录中创建 libs.versions.toml 文件管理所有依赖,子项目中按需引入。该文件分为以下几个部分(里面的内容只是例子):

gradle/libs.versions.toml
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
[versions]
# 版本管理
springBoot = "3.3.3"
springDenpendencyManagement = "1.1.6"

[libraries]
# 依赖管理,有两种编写方式
# 第一种
spring-boot = { group = "org.springframework.boot", name = "spring-boot", version.ref = "springBoot" }
spring-boot-starter-aop = { group = "org.springframework.boot", name = "spring-boot-starter-aop", version.ref = "springBoot" }
# 第二种
spring-boot-starter-security = { module = "org.springframework.boot:spring-boot-starter-security", version.ref = "springBoot" }
spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "springBoot" }

[bundles]
# 依赖分组/打包
spring = [
"spring-boot",
"spring-boot-starter-aop",
"spring-boot-starter-security",
"spring-boot-starter-web"
]

[plugins]
# 插件管理
spring-boot = { id = "org.springframework.boot", version.ref = "springBoot" }
spring-dependency-management = { id = "io.spring.dependency-management", version.ref = "springDenpendencyManagement" }

子模块使用时非常简单:

build.gradle.kts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 使用 libs.versions.toml 定义的插件
plugins {
alias(libs.plugins.xxx)
}

// 使用 libs.versions.toml 定义的依赖
dependencies {
// 单独引入一个依赖
// implementation(libs.spring.boot)

// 引入依赖组,包含组里的所有依赖
// 即引入了 "spring-boot", "spring-boot-starter-aop", "spring-boot-starter-security", "spring-boot-starter-web"
implementation(libs.bundles.spring)
}
  • libs.versions.toml 是 Gradle 默认查找并读取的文件名称,也可以使用其它名称(譬如开发和生产使用不同类型、不同版本的依赖项,可能会定义多个文件),不过需要在 settings.gradle.kts 中做一些配置,让 Gradle 可以读取,配置方式自行查阅 官方文档
  • 版本定义上面使用了 version.ref 的方式,也可以使用 version 直接写版本字符串,例如 spring-boot = { module = "org.springframework.boot:spring-boot", version = "3.3.3" }
  • libs.versions.toml 中定义名称使用 - 分割(spring-boot),但在使用时需要使用 . 分割(libs.spring.boot)。

六、附:CLI 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看帮助
./gradlew -h
./gradlew --status
# 停止 gradle daemon 服务
./gradlew --stop
# 刷新依赖关系的状态。
./gradlew -U 或者 ./gradlew --refresh-dependencies

./gradlew -d, --debug
./gradlew -s, --stacktrace

# 查询依赖
./gradlew dependencies
# 输出依赖到文件中
./gradlew dependencies --console=dependency-tree.txt

本站由 江湖浪子 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。