注意: 如果不是工作原因或是编写安卓项目必须要用Gradle,建议学习Maven即可,Gradle的学习成本相比Maven高很多,而且学了有没有用还是另一回事,所以,作为过来人我不希望浪费大家这几个小时的时间。
欢迎各位小伙伴来到Gradle的学习课程,在开始本课程之前,您需要完成以下前置课程:
Gradle构建工具是一个快速、可靠和适应性强的开源构建自动化工具,具有优雅和可扩展的声明性构建语言,Gradle包含许多优势:
Gradle支持Android、Java、Kotlin Multiplatform、Groovy、Scala、Javascript和C/C++等热门语言的构建工作:
所有常见的IDE都支持Gradle,包括Android Studio、IntelliJ IDEA、Visual Studio Code、Eclipse和NetBeans。
接下来就让我们开始学习Gradle吧。
这一部分我们来学习Gradle的安装和初始化。
在使用Gradle之前,我们先来看看如何安装,这里演示Windows环境下,如何进行安装,其他平台请参考官方文档:https://docs.gradle.org/current/userguide/installation.html#installation
在开始安装之前,首先确保您已经安装好Java环境(使用java --version
命令进行查看)版本不能低于Java 8,本教程使用的是Java 17版本:
确认无误后,我们进入到Gradle官网下载最新版本:下载地址,这里我们选择直接下载已经编译好的二进制文件:
注意: 本教程教学采用的是8.5版本,如果各位小伙伴在学习时官方已经推出了新的版本,请务必选择跟教程相同的版本,因为Gradle的版本兼容性很差,不同版本出现特性变化的情况很常见,容易出现不兼容的情况。
下载完成后解压,然后将解压得到的目录拖到你想要安装的位置,本教程就放到C:\Program Files
目录下:
接着我们需要配置相应的环境变量才能使用,打开环境变量配置面板:
添加环境变量GRADLE_HOME
,变量值为刚刚存放的Gradle文件夹位置。接着我们在Path环境变量中添加对应的bin目录:
添加完成后,我们打开一个新的命令窗口,输入gradle -v
命令查看是否配置生效:
可以看到当前的Gradle相关版本信息已经打印到控制台了。
注意: 如果配置没有生效,可以尝试重启电脑或者查看是否路径编写错误。
安装完成Gradle之后,我们就可以开始正式进行学习了,首先我们还是来尝试创建一个Gradle项目。
这里我们创建一个新的空文件夹用于测试:
接着,我们在当前目录打开CMD窗口,并执行以下命令:
gradle init
出现以下内容,让我们选择当前项目的类型,这里我们选择2
应用类型:
> Task :wrapper
Select type of project to generate:
1: basic
2: application
3: library
4: Gradle plugin
Enter selection (default: basic) [1..4] 2
接着是选择我们程序使用的语言类型,本教程统一使用Java语言讲解,选择3
号:
> Task :init
Select implementation language:
1: C++
2: Groovy
3: Java
4: Kotlin
5: Scala
6: Swift
Enter selection (default: Java) [1..6] 3
接着是是否生成多个子项目结构,我们先按照最简单的单个项目进行讲解,这里直接选择no
即可:
Generate multiple subprojects for application? (default: no) [yes, no] no
接着是编写Gradle脚本采用的语言,目前Gradle支持Kotlin和Groovy两种,且目前官方推荐的是Kotlin语言,所以这里就选择1
号:
Select build script DSL:
1: Kotlin
2: Groovy
Enter selection (default: Kotlin) [1..2] 1
Gradle还需要配置一个测试使用的框架,这里我们选择默认的就行:
Select test framework:
1: JUnit 4
2: TestNG
3: Spock
4: JUnit Jupiter
Enter selection (default: JUnit Jupiter) [1..4]
接着是当前项目的名称以及包名,默认就是当前目录名字,这个自己根据情况选择吧:
Project name (default: Test):
Source package (default: test): com.test
最后是采用的Java版本,因为这里我们安装的是Java17,所以直接输入17即可,还有是否选择使用新特性直接no
就好了:
Enter target version of Java (min. 7) (default: 17): 17
Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no]
接着我们可以看到项目成功完成了初始化操作:
> Task :init
To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.5/samples/sample_building_java_applications.html
BUILD SUCCESSFUL in 12m 38s
2 actionable tasks: 2 executed
现在回到我们的文件夹中,可以看到已经生成了大大小小的文件了:
注意: 不同版本的Gradle对我们使用的IDEA版本同样存在兼容性问题,这里推荐使用IntelliJ IDEA 2023.3
或更高版本,旧版本的IDEA可能会不支持当前的Gradle 8.5版本。
我们可以直接在IDEA中打开这个项目,打开后正常情况下会自动开始初始化,初始化过程中会下载很多东西,包括Gradle当前版本本身,以及它所需要的所有依赖包以及Kotlin相关库:
不对啊,我们本地不是已经安装了Gradle吗,怎么初始化项目的时候又要下载一次呢?这是因为Gradle Wrapper的作用,由于Gradle的跨版本兼容性很差,因此它指定了当前项目中使用的Gradle版本,使得不同的开发人员或CI/CD系统都能使用相同的Gradle版本来构建项目,从而提高项目的一致性和可移植性。Gradle Wrapper的另一个好处是,它可以自动下载和使用正确版本的Gradle,无需手动安装或配置Gradle,使得项目的维护和协作更加方便,后续别人拿到我们这个项目的时候,不需要自己在系统中部署Gradle环境。
这个过程中可能会很卡,因为服务器在国外(建议挂梯)直到出现BUILD SUCCESSFUL
之后,表示初始化完成:
此时我们的项目目录里面已经存在这些内容了:
我们来依次介绍一下这些内容分别代表什么以及有什么作用:
.gradle
:Gradle自动生成的项目缓存目录。.idea
:这个是IDEA的项目配置目录,跟Gradle生成的没关系,无视掉就行。app
:存放整个项目的源代码、测试等,这里面就是我们写代码的地方了。
build.gradle.kts
:项目的gradle构建脚本。src
:存放源代码和测试代码。
main
:编写所有项目核心代码。test
:编写项目测试代码。gradle
:包含JAR文件和Gradle Wrapper的配置。gradlew
:适用于macOS和Linux的使用Gradle Wrapper执行构建的脚本(这里的版本就是GradleWrapper指定的版本)gradlew.bat
:适用于Windows的使用Gradle Wrapper执行构建的脚本。settings.gradle.kts
:定义子项目列表的项目配置文件,也是最关键的设置文件。除了以上文件以外的其他文件,一般都是一些额外的Git文件,例如.gitignore
,不属于Gradle的范畴,无视掉就可以了。
Gradle项目在生成时默认为我们创建了一个测试的主类:
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package com.test;
public class App {
public String getGreeting() {
return "Hello World!";
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
}
}
我们可以在IDEA中尝试直接运行:
这样,咱们的第一个Gradle项目就成功创建并运行了。
我们在一开始就说了,Gradle最主要的目的就是为了构建大型项目,其中构建项目的常用命令非常关键,我们这节课就来学习一下。
首先我们可以查看一下所有Gradle支持的任务,这里我们使用GradleWapper提供的gradlew
进行操作,使用方式其实和gradle
命令是一样的,只是这里用的是生成的(注意Windows平台下需要使用gradlew.bat来运行)
./gradlew.bat task
./gradlew task
其中包含了大量的命令操作:
比如第一个run
命令就可以将当前项目以JVM应用程序的形式运行:
这个命令会自动编译并运行我们的项目,我们也可以手动执行其中的每一步,现在就来尝试一下吧,首先先执行一次清理命令,将整个项目目录进行一次清理,主要清理掉的就是构建出来的文件:
./gradlew clean
我们在编写好一个Java项目之后,第一步就是编译成class文件,然后才能开始运行,所以,我们可以使用以下命令来编译代码:
./gradlew classes
./gradlew classes -q #安静模式,只执行,不打印日志
执行完成之后,如果出现BUILD SUCCESSFUL
表示编译成功,此时在app目录下会生成一个新的build目录,此目录中存放的就是编译之后的相关文件了,其中classes目录存放的就是所有编译之后的class文件:
有些时候我们的项目可能需要在编译之后运行一些测试用例,来快速查看是否存在一些问题,这在开发过程中非常常见,我们可以看到Gradle默认情况下为我们生成了一个简易的测试用例:
class AppTest {
//默认使用的是JUnit作为单元测试工具
@Test void appHasAGreeting() {
App classUnderTest = new App();
//这里是判断如果结果为Null的话就抛出异常
assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
}
}
我们可以将App类中的getGreeting方法的返回值设置为null试试看:
public class App {
public String getGreeting() {
return null;
}
...
}
使用以下命令来执行测试:
./gradlew test
可以看到测试失败了,并且Gradle还自动为我们生成了一个错误报告,其中明确指出了我们出现错误的测试用例:
我们也可以快速执行一个完整的编译+测试流程来构建整个项目,并得到打包好的jar等文件,使用以下命令来完成:
./gradlew build
如果某些时候我们不想执行测试,只想构建整个项目,也可以添加参数跳过:
./gradlew build -x test
只不过这样去敲命令实在是太累了,在IDEA中已经自动帮助我们继承了Gradle插件,我们可以直接展开右侧工具栏,双击就能使用Gradle命令了,非常方便:
前面我们介绍了Gradle项目的搭建与使用,我们先来看一下整个Gradle项目构建的流程:
大概清楚构建流程后,我们接着就来了解一下Gradle项目是如何进行配置的。
设置文件settings.gradle
是整个Gradle项目的入口点:
设置文件用于定义所有的子项目,并让它们参与到构建中,Gradle支持单项目和多项目的构建:
设置文件可以使用Groovy语言(名称为settings.gradle
)或是Kotlin语言(名称为settings.gradle.kts
)编写,本教程一律采用Kotlin语言进行讲解,设置文件通常位于项目的根目录中:
一个标准的Gradle设置文件按照以下样式进行编写,这里使用Kotlin语言介绍:
rootProject.name = "root-project" //rootProject对象代表当前这个项目,其name属性就是当前项目的名称
include("sub-project-a") //所有的子项目使用include()函数进行添加,如果没有子项目可以不写
include("sub-project-b")
include("sub-project-c")
接着我们来看针对于单个项目的构建文件,其中gradle.build
文件就是对应的构建配置,这里我们使用的是Kotlin语言,因此项目中会存在一个gradle.build.kts
文件:
plugins {
id("java")
}
group = "cn.itbaima"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation(platform("org.junit:junit-bom:5.9.1"))
testImplementation("org.junit.jupiter:junit-jupiter")
}
tasks.test {
useJUnitPlatform()
}
可以看到,在这个配置文件中存在大量的Lambda语句,这也使得整个配置文件写起来更加简介美观,所以说虽然Gradle依赖于JVM平台,但是仅支持Kotlin和Groovy,它们相比Java在语法上存在更大的优势,更适合编写这种类似脚本一样的配置文件。
我们首先来看最顶上的plugins函数,后面的Lambda中编写了当前项目需要使用到的插件:
plugins {
id("java")
}
使用id()
函数指定需要使用的插件,这里使用的是java
插件,java
插件将Java编译以及测试和捆绑功能添加到项目中,为建任何类型的 Java 项目提供支持。
当然,除了java插件之外,我们如果需要构建其他类型的项目,也可以使用多种多样的插件:
plugins {
id("cpp-application") //用于构建C++应用程序
}
plugins {
id("swift-application") //用于在MacOS构建Swift应用程序
}
plugins {
id("org.jetbrains.kotlin.jvm") version "1.9.0" //使用version中缀函数为id指定的插件添加版本
}
有关插件相关的内容,我们会在后面的部分深入为大家介绍,不同的插件会为Gradle添加不同的任务。
这里的group和version分别设置了当前项目所属的组名称和版本:
group = "cn.itbaima"
version = "1.0-SNAPSHOT"
接着是所有依赖的仓库配置,默认使用的是Maven中心仓库:
repositories {
mavenCentral()
}
接着是所有的依赖列表,这里默认为我们导入了JUnit相关依赖用于测试:
dependencies {
testImplementation(platform("org.junit:junit-bom:5.9.1"))
testImplementation("org.junit.jupiter:junit-jupiter")
}
最后是任务相关配置,这里对test
任务进行了相关配置:
tasks.test {
useJUnitPlatform()
}
从下节课开始我们来详细介绍一下各个部分。
我们前面介绍了Gradle构建的大致流程和配置文件各个部分,而设置文件settings.gradle.kts
则是整个构建的入口点,在Gradle构建生命周期的早期,初始化阶段会在项目根目录中找到设置文件。
当找到设置文件settings.gradle(.kts)
时,Gradle会实例化一个Settings
对象,我们可以通过此对象来声明要包含在构建中的所有项目,包括我们项目名称的声明也是通过它来完成:
settings.rootProject.name = "untitled"
我们也可以省略掉settings直接使用其提供的属性:
rootProject.name = "untitled"
其中,Settings对象包含以下常用属性:
姓名 | 描述 |
---|---|
buildCache |
项目构建所用缓存配置。 |
plugins |
用于设置的插件。 |
rootDir |
项目构建的根目录,根目录是整个项目目录最外层。 |
rootProject |
构建的根项目。 |
settings |
返回设置对象。 |
Settings对象也包含以下方法可供调用:
姓名 | 描述 |
---|---|
include() |
将指定名称的项目添加到构建列表中。 |
includeBuild() |
添加指定路径上的其他Gradle项目到构建列表中。 |
我们在编写配置文件时,本质上是对Gradle API的一系列方法调用,结合Groovy或Kotlin的{...}
语法(在Groovy中称作闭包,Kotlin中称为Lambda)能够轻松编写非常简洁的配置,比如配置插件:
rootProject.name = "untitled"
plugins { //使用plugins函数配置插件,结合Lambda表达式可以使用简洁语法完成配置
id("test") //瞎写的一个
}
在配置文件中定义的语句,Gradle会一行一行地向下执行,就像一个脚本那样。实际上,我们编写的配置文件在执行Gradle构建时会编译为对应的class文件加载执行,这些文件存放在Gradle的缓存目录中:
因此,我们直接在Gradle配置中编写的自定义语句也可以执行:
这里我们执行了自定义的打印语句,包括可以通过rootProject
对象拿到当前的项目文件File对象等。
在Gradle中,和Maven一样也分为插件和依赖,我们可以在settings.gradle.kt
中可以为所有的项目进行统一配置,比如要修改获取插件的仓库位置:
pluginManagement { //使用pluginManagement函数配置插件仓库列表
repositories { //在repositories函数中配置需要用的仓库
gradlePluginPortal() //Gradle插件仓库
google() //Google插件仓库
}
}
我们也可以修改为国内的阿里云镜像:
pluginManagement {
repositories {
//手动指定maven仓库地址,修改URL地址
maven {
setUrl("https://maven.aliyun.com/repository/public/")
}
}
}
同样的,对于所有的依赖,也可以直接配置为国内的阿里云镜像仓库:
dependencyResolutionManagement { //依赖解析管理中可以配置全局依赖仓库
repositories { //只不过这种方式目前还在孵化阶段,可能会在未来某个版本移除
maven {
setUrl("https://maven.aliyun.com/repository/public/")
}
}
}
不过,除了在settings.gradle.kts
中配置三方仓库之外,我们更推荐在之后学习的build.gradle.kts
中对仓库进行配置。
与Maven一样,Gradle插件可以帮助我们在构建过程中实现各种各样的高级功能,它是用于增加和扩展任务(tasks)或构建逻辑的一种特殊类型的模块,在settings.gradle.kts
中可以配置插件,只不通常被用于需要对多个项目进行操作的插件,或者需要在构建开始之前进行一些配置的情况:
plugins { //使用id明确插件名称,使用version中缀函数明确插件版本
id("org.gradle.toolchains.fake") version "0.6.0"
}
一般很少见有项目在这里配置插件。
对于多个子项目的大型项目而言,我们还需要在这里添加所有的子项目:
include("app")
include("business-logic")
include("data-model")
有关多项目的详细介绍,我们会放在下一个章节,本章节主要以单项目为主。
除了以上提到的内容,Settings
对象上还有更多属性和方法,您可以使用它们来配置构建。不过,虽然许多Gradle脚本通常以简短的Groovy或Kotlin语法编写,但设置脚本中的每个操作都是在Settings
对象上调用方法:
include("app")
settings.include("app") //实际上是这样的,只是说settings可以省掉