学习 gradle 基础
简介
Gradle 的优势
- 一款最新的,功能最强大的构建工具,用它逼格更高
- 使用 Groovy 或者 Kotlin 代替 XML,使用程序代替传统的 XML 配置,项目构建更灵活
- 丰富的第三方插件,让你随心所欲使用
- 完善 Android,Java 开发技术体系
下载和安装
官网地址
https://services.gradle.org/distributions/
PS:下载只有二进制文件的即可(bin 那个压缩包)
百度网盘
链接: https://pan.baidu.com/s/1ZABS5fLyzDmwIs9-v6WSYg?pwd=1111 提取码: 1111
配置环境变量
配置 GRADLE_HOME
配置 PATH
验证 Gradle 是否安装成功
创建第一个 Gradle 项目
点击确认之后,耐心等待IDEA把gradle下载好,网络差的话,等个几十分钟就下载好了
标准项目结构:
基本结构和 maven 是一样的
其中 build.gradle 等价于 maven 中的 pom.xml,是 Gradle 中的项目构建和依赖的主要配置
项目打包
执行
如果出现乱码,在 build.gradle 中加入配置:(更改后重新 clean 再 build)
PS:
build.gradle 构建脚本介绍
Gradle 构建脚本中最重要的两个概念是 project 和 task,任何一个 Gradle 构建都由一个或者多个 project 组成,每个 project 包含许多的构建部分,可以是一个 jar 包,也可以是一个 web 应用,也可以是多个 jar 的整合,可以部署应用和搭建环境
如果有子项目的话
每个项目,对应一个 build.gradle 的构建脚本
Project
一个 Project 代表一个正在构建的组件(Jar / War 文件),当构建开始时,Gradle 会基于 build.gradle 实例化一个 org.gradle.api.Project 对象,并通过 project 变量来隐式调用其成员
Project 属性
名称 | 类型 | 默认值 |
---|---|---|
project | Project | Project 实例 |
name | String | 项目目录的名称 |
path | String | 项目的绝对路径 |
description | String | 项目的描述 |
projectDir | File | 包含生成脚本的目录 |
buildDir | File | projectDir/build |
group | Object | 未指定 |
version | Object | 未指定 |
ant | AntBuilder | AntBuilder 实例 |
将 build.gradle 配置封装为一个 Project 对象,对象名字为 project,通过 project 可以隐式调用,使用 groovy 语法
指定仓库位置:默认情况下使用的是中央仓库,此项目如果需要下载 jar 包从中央仓库下载到本地目录,但是一般我们习惯使用 maven 本地仓库,需要设置 maven 本地仓库
IDEA也需要重新设置 maven 本地库位置
PS:本地仓库的设置对新建项目是生效的
如果需要添加依赖,可以从中央仓库中查找坐标
粘贴过来以后,点击刷新
build.gradle 中的内容
plugins {
id 'java'
}
project.group 'com.msb'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
// https://mvnrepository.com/artifact/org.mybatis/mybatis
implementation group: 'org.mybatis', name: 'mybatis', version: '3.5.9'
}
test {
useJUnitPlatform()
}
PS:Gradle 没有自己的中央仓库,用的就是 maven 的中央仓库
Task
每个任务在构建执行过程中会被封装成org.gradle.api.Task
对象,主要包括任务的动作和任务依赖,任务动作定义了一个原子操作,可以定义依赖其他任务、动作的顺序、执行的条件
任务主要操作动作
dependsOn: 依赖相关操作
doFirst: 任务执行之前执行的方法
doLast、<<(老版本用,现在废弃了):任务执行之后执行的方法
定义好任务后,默认分配在 other 分组下
也可以放在自定义的分组下
任务的定义的方式:(6种定义方式)
// 自定义任务
// 定义方式1:
task(t1, {
group('mytask')
// 配置代码
println '我是任务1'
// 动作代码
doFirst {
println '在任务t1执行前操作的动作代码'
}
// 动作代码
doLast {
println '在任务t1执行后操作的动作代码'
}
})
// 定义方式2
task t2 {
group('mytask')
// 配置代码
println '我是任务2'
// 动作代码
doFirst {
println '在任务t2执行前操作的动作代码'
}
// 动作代码
doLast {
println '在任务t2执行后操作的动作代码'
}
}
// 定义方式3
tasks.create('t3') {
group('mytask')
// 配置代码
println '我是任务3'
}
// 定义方式4
tasks.register('t4') {
group('mytask')
// 配置代码
println '我是任务4'
}
// 定义方式5
tasks {
task t5 {
group('mytask')
// 配置代码
println '我是任务5'
}
}
// 可以一次性定义多个任务 -> 动态任务定义
3.times {
index -> {
task("task${index}") {
group('mytask')
// 配置任务
println "task${index}"
}
}
}
任务的依赖
// 任务依赖
task a {
group('mytask')
doFirst {
println '我是任务a'
}
}
task b(dependsOn:a) { // 代表 b 任务依赖 a 任务 -> 依赖方式通过参数传递
group('mytask')
doFirst {
println '我是任务b'
}
}
task c { // 依赖方式通过内部设置的方式进行依赖
group('mytask')
dependsOn 'b'
doFirst {
println '我是任务c'
}
}
task d {
group('mytask')
doFirst {
println '我是任务d'
}
}
d.dependsOn c // 依赖方式通过外部设置
任务的执行时机
在构建阶段,配置代码是不执行的,在执行阶段,执行动作代码
// 通过 tasks.register 定义的任务,在 build 阶段不执行
// 通过 tasks.register 定义的任务,在任务的执行阶段的配置过程中是执行的
// 通过 tasks.register 定义的任务,配置代码的执行时机是落后于用 task 方式配置的
定位任务
对某个已有额任务进行扩展:例如对 clean 内置任务进行扩展
clean.doLast {
println '我在clean之后执行这个逻辑'
}
tasks.named('clean').get().doFirst {
println '我在clean之前执行这个逻辑'
}
Gradle 项目构建生命周期
Gradle 的生命周期分为三个阶段:初始化阶段、配置阶段、执行阶段
初始化阶段
通过settings.gradle
判断有哪些项目需要初始化,加载所有需要初始化的项目的build.gradle
文件,并为每个项目创建project
对象
配置阶段
执行各项目下的build.gradle
脚本,完成project
的配置,并且构造Task
任务依赖关系图以便在执行阶段按照依赖关系执行Task
中的配置代码
执行阶段
通过配置阶段的Task
图,按顺序执行需要执行的代码中的动作代码,就是执行任务中写在doFirst
或doLast
中的代码
插件
添加插件、发布和使用自定义 jar 包
案例:将自己的项目打成 jar 包,供给另外的项目使用
(1)新建一个 Gradle 项目
(2)配置插件
(3)然后刷新项目,刷新后任务中多了一个分组
(4)配置发布分组:在 build.gradle 中配置我怀疑这里写的不对,因为我根本无法发布到自己的maven仓库中
(5)执行任务,发布 jar 包到本地仓库中
(6)自行去本地库中查找你 jar 包和生成的配置文件
(7)在其它项目中使用刚才本地库中的 jar 包
(8)验证:是否可以使用 jar 包中的内容
自定义插件
(1)在构建脚本中直接编写自定义插件
但是上面的方法只能在当前脚本中使用,不可以在整个项目中使用,如果想要在整个项目中的所有构建脚本中都使用的话,需要将任务单独提取出来放到 buildSrc 下
(2)自己创建 buildSrc 目录
注意点:groovy 目录创建好后一定要是蓝色的文件夹,如果是灰色的文件夹,需要自己构建 build.gradle 脚本,然后加入插件
然后定义插件
定义好以后,就可以在项目的所有 build.gradle 中使用了
Gradle 版本冲突问题
(1)依赖传递性
假设你的项目依赖于一个库,而这个库又依赖于其他库。你不必自己去找出所有这些依赖,你只需要加上你直接依赖的库,Gradle 会隐式的把这些库间接依赖的库也加入到你的项目中
(2)传递性依赖中版本冲突
由于传递性依赖的特点,两个不同版本的 jar 包会被依赖进来,这样就存在版本冲突的问题了
(3)maven中解决冲突的办法——自动解决方案
【1】第一原则:最短路径优先原则
“最短路径优先”意味着项目依赖关系树中路径最短的版本会被使用
例如,假设A、B、C之间的依赖关系是A->B->C->D(2.0) 和 A->E->D(1.0),那么D(1.0)会被使用,因为 A 通过 E 到 D 的路径更短
【2】第二原则:最先声明原则
依赖路径长度是一样的,第一原则不能解决所有问题,比如这样的依赖关系:A->B->Y(1.0),A->C->Y(2.0),Y(1.0)和Y(2.0)的依赖路径长度是一样的,都为2。那么到底谁会被解析使用呢?在 maven 2.0.8 之前的版本中,这是不确定的,但是 maven 2.0.9 开始,为了尽可能避免构建的不稳定性,maven 定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度相等的前提下,在 POM 中依赖声明的顺序决定了谁会被解析使用。顺序最靠前的那个依赖优胜。
(4)Gradle中解决冲突的办法——自动解决方案
Gradle 的默认自动解决版本冲突的方案是选用版本最高的
案例:加入两个依赖
(5)Gradle 中解决冲突的办法——手动修改依赖
手动排除依赖
后续可以自己手动配置你想要的版本的依赖
修改默认配置策略,对所有 jar 包不做冲突自动解决
就会在构建时候抛出异常
手动指定某个 jar 的版本
force:强制覆盖某个版本
多项目构建
在企业中,一个复杂的项目往往是分成几个小项目来协同完成的,这就涉及到多项目的构建,而多项目构建则需要把一个大项目进行项目模块化,通过模块的互相协作完成整个功能。在之前使用 Mavne 的多项目构建时,一般需要一个 root 项目来统一管理所有的模块,Gradle 也一样使用一个 root 项目来统一管理所有的模块
案例:
构建
配置:
配置1:统一插件配置:在根项目的 build.gradle 中配置
配置2:统一配置公共属性
配置3:配置项目的依赖关系,在子项目的 build.gradle 中配置
验证
配置4:统一资源库
配置5:配置公用的依赖:配置在根项目的 build.gradle 中
PS:如果配置在 subprojects 外面,就只针对根生效,对子项目无效,只有放在 subprojects 中对所有项目生效
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?