第一章:Gradle 任务简介
1.1 概述
- Gradle 项目中会包含若干个任务(task)进行描述,同时每个任务定义的语句形式都是利用 Groovy 语法完成的(现在也支持 kotlin 了)。
- 在一个 Gradle 项目中利用任务的概念,可以将一个完整的处理任务拆分成若干个细小的子任务。
1.2 任务列表
- 当创建完成一个 Gradle 项目之后,默认情况下都会存在若干个任务列表,可以直接通过 Gradle 命令查看:
gradle -q tasks

- 其实,在 IDEA 中展示的就是这些任务列表:

1.3 项目属性
- Gradle 项目是基于 Groovy 语言编写的,所以在使用 Groovy 操作 Gradle 项目的时候需要获取一些项目的信息,可以通过如下的命令获取所有的项目属性:
gradle -q properties

1.4 任务定义
- 清楚了
项目和任务的基本关系之后,下面就需要动手来直接定义一个任务,所有的任务定义都是使用 Groovy 语法来完成的,所有的任务都可以直接在build.gradle文件里面进行定义处理。
plugins {id 'java' // 配置的是一个 Java 插件(Java 项目)}group 'com.github.fairy.era' // 组织名称version '1.0' // 项目版本sourceCompatibility = 1.8 // 源代码版本repositories { // 仓库配置mavenCentral()}dependencies { // 依赖管理/* junit 5 */testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'}tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置options.encoding = "UTF-8"}test { // 进行测试任务的配置useJUnitPlatform() // 使用 Junit 平台}task hello { // 定义一个新的任务,任务的名称是 helloprintln('你好,Gradle')}
- 当任务定义完成之后,会自动的在 Gradle 命令执行列表中出现有任务的名称信息。

- 当然,也可以通过执行命令来执行该任务:
gradle hello
第二章:Gradle 任务定义语法
2.1 概述
- 通过之前的具体操作,已经成功的实现了一个 Gradle 自定义的任务项,但是需要注意的是,在 Gradle 里面任务的定义语法形式是非常丰富的,所以本次来研究一下各种任务的定义语法形式。
2.2 原型创建
- 在 Gradle 里面提供了一个 task() 处理函数,这个函数可以直接创建一个任务,同时需要设置好任务的名称。
- 对于任务的创建主要通过 org.gradle.api.Project 接口里面提供的任务创建方法:
Task task(String var1) throws InvalidUserDataException;
- 在使用 task() 方法进行任务创建的时候,需要设置一个字符串,修改
build.gradle文件:
// 每一个创建出来的任务都是 Task(org.gradle.api.Task) 的对象实例def task = task(helloTask) // 创建一个任务:helloTask
- 每当使用
task()方法创建的任务都自动返回一个 Task 接口的实例,Task 接口的定义如下:
package org.gradle.api;public interface Task extends Comparable<Task>, ExtensionAware {String TASK_NAME = "name";String TASK_DESCRIPTION = "description";String TASK_GROUP = "group";String TASK_TYPE = "type";String TASK_DEPENDS_ON = "dependsOn";String TASK_OVERWRITE = "overwrite";String TASK_ACTION = "action";String TASK_CONSTRUCTOR_ARGS = "constructorArgs";// 其他略}
- 当获取到了一个 Task 接口的实例之后,就需要进行此任务的具体执行行为的配置(任务体),修改
build.gradle文件:
// 每一个创建出来的任务都是 Task(org.gradle.api.Task) 的对象实例def task = task(helloTask) // 创建一个任务:helloTasktask.doLast { // 在任务之后执行此操作println '你好啊,Groovy'}
2.3 任务属性
- 在创建 task 的时候,有可以使用 Project 接口中提供的其他的创建方法,同时设置好一些相应的任务的属性内容。
- 任务的创建方法:
Task task(Map<String, ?> var1, String var2) throws InvalidUserDataException;
- 设置任务的属性,修改
build.gradle文件:
// 每一个创建出来的任务都是 Task(org.gradle.api.Task) 的对象实例def task = task(description: '自定义 Gradle 任务的描述', helloTask) // 创建一个任务:helloTasktask.doLast { // 在任务之后执行此操作println '你好啊,Groovy'}
- 程序执行命令:
gradle helloTask
- 程序执行结果:
14:11:10: 正在执行 'helloTask'…> Task :helloTask你好啊,GroovyBUILD SUCCESSFUL in 50ms1 actionable task: 1 executed14:11:10: 执行完成 'helloTask'。
- 程序执行命令:
gradle help --task helloTask
- 程序执行结果:
14:11:20: 正在执行 'help --task helloTask'…> Task :helpDetailed task information for helloTaskPath:helloTaskTypeTask (org.gradle.api.Task)Description自定义 Gradle 任务的描述Group-BUILD SUCCESSFUL in 44ms1 actionable task: 1 executed14:11:20: 执行完成 'help --task helloTask'。
- 这些描述信息可以直接在进行任务帮助的时候进行详细的显示操作。
- 设置更多的属性内容,修改
build.gradle文件:
// 每一个创建出来的任务都是 Task(org.gradle.api.Task) 的对象实例def task = task([description: '自定义 Gradle 任务的描述',group: 'com.github.fairy.era'], helloTask) // 创建一个任务:helloTasktask.doLast { // 在任务之后执行此操作println '你好啊,Groovy'}
- 程序执行命令:
gradle help --task helloTask
- 程序执行结果:
14:14:28: 正在执行 'help --task helloTask'…> Task :helpDetailed task information for helloTaskPath:helloTaskTypeTask (org.gradle.api.Task)Description自定义 Gradle 任务的描述Groupcom.github.fairy.eraBUILD SUCCESSFUL in 56ms1 actionable task: 1 executed14:14:28: 执行完成 'help --task helloTask'。
2.4 闭包机制
- 在 Groovy 这种提供闭包的处理操作机制,也可以用这样的语法形式来实现 Task 的创建,修改
build.gradle文件:
task helloTask { // 进行任务的创建description '自定义 Gradle 任务的描述'group 'com.github.fairy.era'doLast {println '你好啊,Groovy'}}
- 需要注意的是,如果修改了 group 属性,那么任务项将不在 other 任务列表中显示了:

- 程序执行命令:
gradle help --task helloTask
- 程序执行结果:
14:27:39: 正在执行 'help --task helloTask'…> Task :helpDetailed task information for helloTaskPath:helloTaskTypeTask (org.gradle.api.Task)Description自定义 Gradle 任务的描述Groupcom.github.fairy.eraBUILD SUCCESSFUL in 39ms1 actionable task: 1 executed14:27:39: 执行完成 'help --task helloTask'。
- 以上这种任务创建的形式是比较正统的一种形式,因为这样操作的语法相对而言简单一些,但是需要注意的是,同样的定义形式在 Gradle 中也可以采用如下的两种方式代替,修改
build.gradle文件:
task (helloTask) { // 进行任务的创建description '自定义 Gradle 任务的描述'group 'com.github.fairy.era'doLast {println '你好啊,Groovy'}}
task (helloTask, { // 进行任务的创建description '自定义 Gradle 任务的描述'group 'com.github.fairy.era'doLast {println '你好啊,Groovy'}})
2.5 TaskContainer
- 在 Gradle 中提供有一个 TaskContainer(任务容器) 的概念实现任务的创建操作,首先来观察当前这种任务创建的方法定义:
// 此方法在 org.gradle.api.tasks.TaskContainer 中定义Task create(Map<String, ?> var1, Closure var2) throws InvalidUserDataException;
- 创建自定义任务,修改
build.gradle文件:
tasks.create('helloTask') {description '自定义 Gradle 任务的描述'group 'com.github.fairy.era'doLast {println '你好啊,Groovy'}}
- 程序执行命令:
gradle help --task helloTask
- 程序执行结果:
14:43:31: 正在执行 'help --task helloTask'…> Task :helpDetailed task information for helloTaskPath:helloTaskTypeTask (org.gradle.api.Task)Description自定义 Gradle 任务的描述Groupcom.github.fairy.eraBUILD SUCCESSFUL in 58ms1 actionable task: 1 executed14:43:32: 执行完成 'help --task helloTask'。
第三章:Gradle 任务属性
3.1 概述
- 在每一个任务之中都会存在若干个属性信息,如:描述(description)、任务的分组(group),这些都属于任务属性,但是除了这些任务属性之外,还有一些关于任务继承相关的属性存在。
3.2 属性设置
- 所有的任务属性除了在任务定义的时候进行设置之外,还可以直接通过任务对象进行设置,修改
build.gradle文件:
def ta = task helloTask { // 进行任务的创建doFirst {println '【doFirst】你好,Groovy'}doLast {println '【doLast】 你好,Groovy'}}// 属性设置ta.group = 'com.github.fairy.era'

- 在进行任务分组的时候,为了方便起见也可以将其归纳到内置的 Gradle 任务分组之中,此时可以直接使用 BasePlugin 类中提供的一系列常量来进行配置。
public class BasePlugin implements Plugin<Project> {public static final String CLEAN_TASK_NAME = "clean";public static final String ASSEMBLE_TASK_NAME = "assemble";public static final String BUILD_GROUP = "build";public static final String UPLOAD_ARCHIVES_TASK_NAME = "uploadArchives";public static final String UPLOAD_GROUP = "upload";// 其余略}
- 将任务分组归纳到内置的 Gradle 任务分组之中,修改
build.gradle文件(以下写法,任选一种即可):
def ta = task helloTask { // 进行任务的创建doFirst {println '【doFirst】你好,Groovy'}doLast {println '【doLast】 你好,Groovy'}}// 属性设置ta.group = BasePlugin.BUILD_GROUP // 设置任务所在的分组ta.description = '自定义 Gradle 的任务描述'
def ta = task helloTask { // 进行任务的创建doFirst {println '【doFirst】你好,Groovy'}doLast {println '【doLast】 你好,Groovy'}}// 属性设置helloTask { // 定义任务属性内容group = BasePlugin.BUILD_GROUP // 设置任务所在的分组description = '自定义 Gradle 的任务描述' // 定义任务描述}

3.3 控制属性
- 既然任务已经可以直接创建了,并且所创建的任务也都可以正常执行,那么就可以通过任务属性的配置来设置某一个任务是否可以启动,修改
build.gradle文件:
def ta = task helloTask { // 进行任务的创建doFirst {println '【doFirst】你好,Groovy'}doLast {println '【doLast】 你好,Groovy'}}// 属性设置helloTask { // 定义任务属性内容group = BasePlugin.BUILD_GROUP // 设置任务所在的分组description = '自定义 Gradle 的任务描述' // 定义任务描述enabled = false // 任务禁用}
- 程序执行命令:
gradle helloTask
- 程序执行结果:
20:59:38: 正在执行 'helloTask'…> Task :helloTask SKIPPEDBUILD SUCCESSFUL in 40ms20:59:38: 执行完成 'helloTask'。
3.4 自定义任务类型(任务继承)
- 在 Gradle 里面,如果自定义的任务类型不能满足实际的开发需求时,最简单的方法就是编写自定义的任务类型,其只需要继承 DefaultTask 父类即可,修改
build.gradle文件:
class CustomTask extends DefaultTask {@TaskAction // 必须追加任务执行的注解def doSelf() { // 定义任务的主体println '【CustomTask - doSelf】 - 执行任务的主体'}@TaskActiondef doLast() {println '【CustomTask - doLast】 - 任务主体执行完毕后的操作'}}task helloTask(type: CustomTask) { // 进行任务的创建group = BasePlugin.BUILD_GROUP // 设置任务所在的分组description = '自定义 Gradle 的任务描述' // 定义任务描述doFirst {println '【doFirst】你好,Groovy'}doLast {println '【doLast】 你好,Groovy'}}
- 程序执行命令:
gradle helloTask
- 程序执行结果:
8:09:04: 正在执行 'helloTask'…> Task :helloTask【doFirst】你好,Groovy【CustomTask - doLast】 - 任务主体执行完毕后的操作【CustomTask - doSelf】 - 执行任务的主体【doLast】 你好,GroovyBUILD SUCCESSFUL in 53ms1 actionable task: 1 executed8:09:05: 执行完成 'helloTask'。
3.5 onlyif
- 在任务执行的时候还有一个 onlyif 属性,这个属性的含义可以接收一个闭包的处理,根据处理的结果来判断此任务是否要执行(回调机制,如果返回 true ,就表示需要执行;如果返回 false ,就表示不需要执行),修改
build.gradle文件:
final String BUILD_TASK_NAME = 'hello'task helloTask {group BasePlugin.BUILD_GROUPdescription '自定义 Gradle 的任务描述'onlyIf { // 此属性类似于 enabled 的形式def executeResult = false // 执行的最终结果// 对于此任务是否执行,取决于外部设置的一个属性内容,即在执行命令的时候所配置的属性内容if (project.hasProperty('flag')) { // 判断是否存在 flag 配置属性def flagProperties = project.property('flag') // 获取属性内容if (BUILD_TASK_NAME == flagProperties) { // 和内置属性相同executeResult = true // 要执行此任务}}return executeResult // 根据此结果来判断是否执行任务}doLast {println '你好啊,Groovy'}}
- 程序执行命令:
gradle helloTask
- 程序执行结果:
8:44:17: 正在执行 'helloTask'…> Task :helloTask SKIPPEDBUILD SUCCESSFUL in 48ms8:44:17: 执行完成 'helloTask'。
- 程序执行命令:
gradle -Pflag=hello helloTask
- 程序执行结果:
8:46:43: 正在执行 'helloTask -Pflag=hello'…> Task :helloTask你好啊,GroovyBUILD SUCCESSFUL in 50ms1 actionable task: 1 executed8:46:43: 执行完成 'helloTask -Pflag=hello'。
第四章:Gradle 多任务定义
4.1 概述
- 通过之前的一系列分析,我们已经清楚的知道单个任务的定义语法,但是很多情况下有可能需要在一个 Gradle 项目里面定义若干个任务,如:gradle clean build,那么现在就尝试如何在 Gradle 里面实现多个任务的定义和执行。
4.2 多任务
- 在 build.gradle 文件中定义三个任务信息,修改
build.gradle文件:
task helloTask1 { // 第一个执行任务println '【第一个执行任务】'}task helloTask2 { // 第二个执行任务println '【第二个执行任务】'}task helloTask3 { // 第三个执行任务println '【第三个执行任务】'}
- 程序执行命令:
gradle helloTask2 helloTask1 helloTask3
- 程序执行结果:
8:58:09: 正在执行 'helloTask2 helloTask1 helloTask3'…> Configure project :【第一个执行任务】【第二个执行任务】【第三个执行任务】> Task :helloTask2 UP-TO-DATE> Task :helloTask1 UP-TO-DATE> Task :helloTask3 UP-TO-DATEBUILD SUCCESSFUL in 65ms8:58:09: 执行完成 'helloTask2 helloTask1 helloTask3'。
- 通过此时的多任务的执行结果,可以发现,在 build.gradle 里面定义的多个任务信息,实际上都会根据其定义的顺序来执行,而不是由 gradle 命令配置的顺序来执行。
4.3 任务依赖
- 既然已经存在了多个任务,那么这些任务彼此之间就可能存在有依赖关系(任务 A 依赖于 任务 B ,如:进行打包之前必须先进行编译之后,才能进行打包),这样的依赖关系就可以通过 dependsOn 来进行配置,修改
build.gradle文件:
// 注意:所有依赖的任务彼此之间一定要有一个顺序,被依赖的任务一定要在之前进行定义task helloTask1 { // 第一个执行任务doLast {println '【第一个执行任务】'}}task helloTask2 { // 第二个执行任务doLast {println '【第二个执行任务】'}}task helloTask3(dependsOn: [helloTask1, helloTask2]) { // 第三个执行任务,当前的任务依赖于前面的两个任务doLast {println '【第三个执行任务】'}}task allTask(dependsOn: helloTask3) { // 总的执行任务doFirst {println 'allTask doFirst'}}
- 程序执行命令:
gradle allTask
- 程序执行结果:
9:11:17: 正在执行 'allTask'…> Task :helloTask1【第一个执行任务】> Task :helloTask2【第二个执行任务】> Task :helloTask3【第三个执行任务】> Task :allTaskallTask doFirstBUILD SUCCESSFUL in 51ms4 actionable tasks: 4 executed9:11:17: 执行完成 'allTask'。
- 可以发现,所有被依赖的任务会首先执行,而所有要执行的任务都会最后执行。
4.4 任务禁用
- 在之前学习任务属性的时候,学习过一个 enabled 属性,这个属性的内容会决定当前的任务是否执行,那么如果说被依赖的任务没有执行,那么会不会影响到其他的任务?修改
build.gradle文件:
task helloTask1 { // 第一个执行任务enabled false // 此任务直接跳过doLast {println '【第一个执行任务】'}}task helloTask2 { // 第二个执行任务doLast {println '【第二个执行任务】'}}task helloTask3(dependsOn: [helloTask1, helloTask2]) { // 第三个执行任务,当前的任务依赖于前面的两个任务enabled false // 此任务直接跳过doLast {println '【第三个执行任务】'}}task allTask(dependsOn: helloTask3) { // 总的执行任务doFirst {println 'allTask doFirst'}}
- 程序执行命令:
gradle allTask
- 程序执行结果:
9:16:19: 正在执行 'allTask'…> Task :helloTask1 SKIPPED> Task :helloTask2【第二个执行任务】> Task :helloTask3 SKIPPED> Task :allTaskallTask doFirstBUILD SUCCESSFUL in 334ms2 actionable tasks: 2 executed9:16:20: 执行完成 'allTask'。
- 此时存在的依赖关系,即便父任务没有执行,那么子任务也依然正确执行。
第五章:Gradle 任务定义深入
5.1 概述
- 现在已经清楚了 Gradle 任务定义的大部分的操作语法,实际上除了这些基础的语法之外,在任务处理的时候也存在着一些项目的属性、方法等信息。
5.2 任务属性
- 所有的任务实际上都会放在 TaskContainer 中进行任务管理(也是在项目中保存),那么如果要想在任务中获取到一些任务的属性,也是可以直接完成的,修改
build.gradle文件:
task helloTask {doFirst {println '常规输出:你好,Gradle!!!'println '任务名称 - 1:' + helloTask.name // 任务名称获取println '任务名称 - 2:' + project.helloTask.name // 项目中的任务名称获取println '任务名称 - 3:' + tasks.helloTask.name // 任务容器获取任务名称println '任务名称 - 4:' + tasks['helloTask'].name // 任务容器获取任务名称}}
- 程序执行命令:
gradle helloTask
- 程序执行结果:
9:43:55: 正在执行 'helloTask'…> Task :helloTask常规输出:你好,Gradle!!!任务名称 - 1:helloTask任务名称 - 2:helloTask任务名称 - 3:helloTask任务名称 - 4:helloTaskBUILD SUCCESSFUL in 48ms1 actionable task: 1 executed9:43:55: 执行完成 'helloTask'。
5.3 任务路径
- 在每一个任务里面都会存在有任务路径,通常而言,建议任务路径名称和任务名称相同,修改
build.gradle文件:
task helloTask {doFirst {println '常规输出:你好,Gradle!!!'println '任务路径 - 1:' + helloTask.path // 任务路径获取println '任务路径 - 2:' + project.helloTask.path // 项目中的任务路径获取println '任务路径 - 3:' + tasks.helloTask.path // 任务容器获取任务路径println '任务路径 - 4:' + tasks['helloTask'].path // 任务容器获取任务路径println '任务路径 - 5:' + tasks.getByPath('helloTask').path // 任务路径获取println '任务路径 - 6:' + tasks.getByPath(':helloTask').path // 任务路径获取}}
- 程序执行命令:
gradle :helloTask
- 程序执行结果:
9:50:36: 正在执行 ':helloTask'…> Task :helloTask常规输出:你好,Gradle!!!任务路径 - 1::helloTask任务路径 - 2::helloTask任务路径 - 3::helloTask任务路径 - 4::helloTask任务路径 - 5::helloTask任务路径 - 6::helloTaskBUILD SUCCESSFUL in 56ms1 actionable task: 1 executed9:50:36: 执行完成 ':helloTask'。
总结:整个 Gradle 中的项目信息是通过 project 得到的,对应的属性是通过 property() 方法获取,而所有的任务信息都可以通过 tasks(TasksContainer) 来获取,里面保存的就是一个 Map 集合。
5.4 任务顺序
- 对于任务来说,在整个 Gradle 里面有各种各样的处理语法,在之前也已经学习过一种最为简单的多任务执行操作,而当时定义的多任务是直接使用 task 的形式创建的,这样的创建形式在执行的时候,就会按照定义的顺序执行任务,但是如果此时采用的是下面的语法形式,则可以根据执行的顺序来进行配置,修改
build.gradle文件:
def taskA = task helloTask {doFirst {println '你好啊,Groovy 中的 helloTask'}}def taskB = task helloTask1 {doFirst {println '你好啊,Groovy 中的 helloTask1'}}
- 程序执行命令:
gradle helloTask1 helloTask
- 程序执行结果:
10:01:23: 正在执行 'helloTask1 helloTask'…> Task :helloTask1你好啊,Groovy 中的 helloTask1> Task :helloTask你好啊,Groovy 中的 helloTaskBUILD SUCCESSFUL in 192ms2 actionable tasks: 2 executed10:01:23: 执行完成 'helloTask1 helloTask'。
- 但是,此时希望不管什么时候都希望 helloTask1 在 helloTask 之后执行,所以此时就可以通过配置顺序的形式来定义任务的执行顺序,修改
build.gradle文件:
def taskA = task helloTask {doFirst {println '你好啊,Groovy 中的 helloTask'}}def taskB = task helloTask1 {doFirst {println '你好啊,Groovy 中的 helloTask1'}}// B 任务用于在 A任务之后执行taskB.mustRunAfter(taskA)
- 程序执行命令:
gradle helloTask1 helloTask
- 程序执行结果:
10:04:29: 正在执行 'helloTask1 helloTask'…> Task :helloTask你好啊,Groovy 中的 helloTask> Task :helloTask1你好啊,Groovy 中的 helloTask1BUILD SUCCESSFUL in 96ms2 actionable tasks: 2 executed10:04:29: 执行完成 'helloTask1 helloTask'。
- 通过此时的执行结果可以清楚的发现:即便执行的时候任务的顺序没有设置好,但是由于在 build.gradle 文件中设置好了任务执行的顺序,那么所有的任务也会按照事前设置好的顺序依次执行。
5.5 任务错误
- 当在配置任务的时候,使用了 mustRunAfter 属性之后,如果还同时存在有依赖的关系,那么很有可能会存在递归任务的错误之中, 修改
build.gradle文件:
def taskA = task helloTask {doFirst {println '你好啊,Groovy 中的 helloTask'}}def taskB = task helloTask1 {doFirst {println '你好啊,Groovy 中的 helloTask1'}}// 依赖环境的配置taskA.dependsOn(taskB)// B 任务用于在 A任务之后执行taskB.mustRunAfter(taskA)
- 程序执行命令:
gradle helloTask
- 程序执行结果:
Circular dependency between the following tasks::helloTask\--- :helloTask1\--- :helloTask (*)* Try:Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
- 按照任务依赖,可能会先执行被依赖的任务,然后在执行本身的任务,但是按照 mustRunAfter 的做法,需要配置任务的执行顺序,所以此时会出现一个程序的递归错误。
5.6 依赖顺序解决
- 在庞大的 Gradle 项目开发过程之中,你很难保证不出现上面的任务错误(程序的递归错误),所以最佳的做法就是忽略递归执行任务的死循环,修改
build.gradle文件:
def taskA = task helloTask {doFirst {println '你好啊,Groovy 中的 helloTask'}}def taskB = task helloTask1 {doFirst {println '你好啊,Groovy 中的 helloTask1'}}// 依赖环境的配置taskA.dependsOn(taskB)// B 任务用于在 A任务之后执行,修改这边啊,将 mustRunAfter 改为 shouldRunAftertaskB.shouldRunAfter(taskA)
- 程序执行命令:
gradle helloTask
- 程序执行结果:
10:18:40: 正在执行 'helloTask'…> Task :helloTask1你好啊,Groovy 中的 helloTask1> Task :helloTask你好啊,Groovy 中的 helloTaskBUILD SUCCESSFUL in 48ms2 actionable tasks: 2 executed10:18:40: 执行完成 'helloTask'。
- 此时并没有强制性的发生任务先后执行的顺序逻辑,而是采用了一种较为柔和的方式来完成任务执行顺序的配置。
5.7 任务替换
- 按照 Java 程序,如果父类中的某个操作方法不好用,那么子类就可以考虑进行方法的扩展(通过重写来解决此问题);同样的问题也出现在 Gradle 之中,虽然 Gradle 提供了大量的内置的操作方法,但是如果我们发现某些操作方法不合适,那么也可以进行重写,修改
build.gradle文件(以下方式,任选其一即可):
task build(overwrite: true) {doFirst {println '你好啊,Gradle'}}
def task = task([overwrite: true], build) {doFirst {println '你好啊,Gradle'}}
- 程序执行命令:
gradle build
- 程序执行结果:
10:48:54: 正在执行 'build'…> Task :compileJava UP-TO-DATE> Task :processResources NO-SOURCE> Task :classes UP-TO-DATE> Task :jar> Task :assemble> Task :compileTestJava UP-TO-DATE> Task :processTestResources NO-SOURCE> Task :testClasses UP-TO-DATE> Task :test> Task :check> Task :build你好啊,GradleBUILD SUCCESSFUL in 813ms5 actionable tasks: 3 executed, 2 up-to-date10:48:55: 执行完成 'build'。
5.8 任务失败
- 既然现在操作的是多任务,那么多任务彼此之间就可能有任务会出现失败情况,那么如果有的任务失败了会影响到其他的任务吗?为了模拟任务的失败,手动抛出一个任务停止的异常,修改
build.gradle文件:
def taskA = task helloTask {doFirst {if (true) {throw new StopExecutionException('我出异常了,你能拿我咋办?')}println '你好啊,Groovy 中的 helloTask'}}def taskB = task helloTask1 {dependsOn taskAdoFirst {println '你好啊,Groovy 中的 helloTask1'}}
- 程序执行命令:
gradle helloTask1
- 程序执行结果:
10:58:44: 正在执行 'helloTask1'…> Task :helloTask> Task :helloTask1你好啊,Groovy 中的 helloTask1BUILD SUCCESSFUL in 44ms2 actionable tasks: 2 executed10:58:44: 执行完成 'helloTask1'。
- 虽然此时第一个任务中产生了各种异常,但是并不影响到后续的其他任务的执行。
第六章:Gradle 文件处理任务
6.1 概述
- 在以后编写最多的处理任务就是进行项目中各类资源文件的控制了,按照一个正规的项目开发来说,肯定需要提供有 resources、config 之类的文件目录,这些文件目录在进行打包的时候,肯定要将其全部打包的目标目录之中,此时就需要进行文件操作了。
6.2 文件创建
- 既然要打包,通常而言都会提供一些配置的目录,同时在配置目录下会存在有许多
*.properties的文件,在 src 目录下创建一个 config/database.properties 文件,内容如下:
# 随便写druid.database.name=erp

6.3 文件定位
- 如果要进行各种资源文件的处理,那么首先肯定需要解决的就是文件定位的问题了,修改
build.gradle文件:
task fileTask { // 文件处理任务doFirst {// org.gradle.api.Project 提供的 File file(Object var1);File configFileA = file('src/config/database.properties')println '【文件定位 - A】' + configFileA// 如果觉得以上的 file() 方式不习惯,那么也可以按照传统的方式编写完整路径File configFileB = file(new File('src' + File.separator + 'config' + File.separator + 'database.properties'))println '【文件定位 - B】' + configFileB}}
- 程序执行命令:
gradle fileTask
- 程序执行结果:
13:32:23: 正在执行 'fileTask'…> Task :fileTask【文件定位 - A】D:\project\gradle-01\src\config\database.properties【文件定位 - B】D:\project\gradle-01\src\config\database.propertiesBUILD SUCCESSFUL in 204ms1 actionable task: 1 executed13:32:23: 执行完成 'fileTask'。
- 在 Gradle 里面可以使用 Project 接口所提供的 file() 函数,直接针对于当前项目中的资源进行定位处理。
6.4 资源集合
- 如果一个项目中包含多种资源,那么也可以考虑使用资源集合的形式进行配置,在 src 目录下创建一个 config/dubbo.properties 文件,内容如下:
dubbo.application.name=gradle

- 修改
build.gradle文件:
task fileTask { // 文件处理任务doFirst {// org.gradle.api.Project 提供的 ConfigurableFileCollection files(Object... var1);def fileCollection = files('src/config/database.properties','src/config/dubbo.properties')fileCollection.each { File file ->println file}}}
- 程序执行命令:
gradle fileTask
- 程序执行结果:
13:45:57: 正在执行 'fileTask'…> Task :fileTaskD:\project\gradle-01\src\config\database.propertiesD:\project\gradle-01\src\config\dubbo.propertiesBUILD SUCCESSFUL in 47ms1 actionable task: 1 executed13:45:58: 执行完成 'fileTask'。
- 通过 files 函数返回的是一个 FileCollection 文件集合,这个集合属于一个可迭代的对象,所以可以使用 each() 函数。
6.5 集合操作
- 通过 FileCollection 可以获取文件的集合,但是有些情况下可能需要对集合中的内容进行扩充,在 src 目录下创建一个 config/redis.properties 文件,内容如下:
redis.server.address=192.168.0.1

- 修改
build.gradle文件:
task fileTask { // 文件处理任务doFirst {// org.gradle.api.Project 提供的 ConfigurableFileCollection files(Object... var1);def fileCollection = files('src/config/database.properties', 'src/config/dubbo.properties')def union = fileCollection + files('src/config/redis.properties') // 集合相加union.each { File file -> // 输出相加后的集合println file}println '----------------------------'def diff = fileCollection - files('src/config/database.properties')diff.each { File file -> // 输出相减后的集合println file}println '----------------------------'println '【增加后的集合】' + union.files // 输出全部的内容println '【减少后的集合】' + diff.singleFile // 单个集合中的内容,必须确定集合中只有一个}}
- 程序执行命令:
gradle fileTask
- 程序执行结果:
14:08:55: 正在执行 'fileTask'…> Task :fileTaskD:\project\gradle-01\src\config\database.propertiesD:\project\gradle-01\src\config\dubbo.propertiesD:\project\gradle-01\src\config\redis.properties----------------------------D:\project\gradle-01\src\config\dubbo.properties----------------------------【增加后的集合】[D:\project\gradle-01\src\config\database.properties, D:\project\gradle-01\src\config\dubbo.properties, D:\project\gradle-01\src\config\redis.properties]【减少后的集合】D:\project\gradle-01\src\config\dubbo.propertiesBUILD SUCCESSFUL in 251ms1 actionable task: 1 executed14:08:56: 执行完成 'fileTask'。
6.6 文件列表
- 以上的做法是将所有文件的完整路径进行单独的配置,这样的配置实在是太繁琐了,那么就可以考虑指定目录下的文件进行全部加载操作,修改
build.gradle文件:
task fileTask { // 文件处理任务doFirst {File configFile = file('src/config') // 定位要使用的文件路径def fileCollection = files(configFile.listFiles()) // 文件列表fileCollection.each {File file ->println file}}}
- 程序执行命令:
gradle fileTask
- 程序执行结果:
14:16:05: 正在执行 'fileTask'…> Task :fileTaskD:\project\gradle-01\src\config\database.propertiesD:\project\gradle-01\src\config\dubbo.propertiesD:\project\gradle-01\src\config\redis.propertiesBUILD SUCCESSFUL in 54ms1 actionable task: 1 executed14:16:05: 执行完成 'fileTask'。
- 此时直接设置了一个加载的目录,随后就可以将此目录中的全部内容进行自动的加载,整个的程序实在是太容易了。
6.7 文件树
- 文件树指的是一个按照层次结构分布的文件集合,如:一个文件树可以描述一个目录的组成结构,而在 Gradle 里面可以直接通过 fileTree() 来生成这样的文件树,修改
build.gradle文件:
task fileTask { // 文件处理任务doFirst {def tree = fileTree('src') // 对 src 目录进行列表tree.exclude('**/*.java') // 不显示 *.java 源文件tree.include ('**/*.properties','**/*.xml')tree.visit { element -> // 查看整个文件树的全部内容println element}}}
- 程序执行命令:
gradle fileTask
- 程序执行结果:
14:26:52: 正在执行 'fileTask'…> Task :fileTaskfile 'D:\project\gradle-01\src\config'file 'D:\project\gradle-01\src\config\database.properties'file 'D:\project\gradle-01\src\config\dubbo.properties'file 'D:\project\gradle-01\src\config\redis.properties'file 'D:\project\gradle-01\src\main'file 'D:\project\gradle-01\src\main\java'file 'D:\project\gradle-01\src\main\java\com'file 'D:\project\gradle-01\src\main\java\com\github'file 'D:\project\gradle-01\src\main\java\com\github\fairy'file 'D:\project\gradle-01\src\main\java\com\github\fairy\era'file 'D:\project\gradle-01\src\main\java\com\github\fairy\era\service'file 'D:\project\gradle-01\src\main\java\com\github\fairy\era\service\impl'file 'D:\project\gradle-01\src\main\resources'file 'D:\project\gradle-01\src\test'file 'D:\project\gradle-01\src\test\java'file 'D:\project\gradle-01\src\test\java\com'file 'D:\project\gradle-01\src\test\java\com\github'file 'D:\project\gradle-01\src\test\java\com\github\era'file 'D:\project\gradle-01\src\test\java\com\github\era\fairy'file 'D:\project\gradle-01\src\test\java\com\github\era\fairy\service'file 'D:\project\gradle-01\src\test\resources'BUILD SUCCESSFUL in 54ms1 actionable task: 1 executed14:26:52: 执行完成 'fileTask'。
6.8 源文件目录
- 在所有的构建工具创建的项目里面一般都会包含有源文件的目录,这些源文件的目录也可以直接在任务中进行访问,但是首先需要明确的定义出可能包含的源文件目录,修改
build.gradle文件:
sourceSets { // 建立源代码的目录集合main {java {srcDirs = ['src/main/java']}resources {srcDirs = ['src/main/resources', 'src/config']}}}task fileTask { // 文件处理任务doFirst {sourceSets.main.allJava.each { File file ->println file}println '-------------------'sourceSets.main.resources.each { File file ->println file}}}
- 程序执行命令:
gradle fileTask
- 程序执行结果:
14:44:34: 正在执行 'fileTask'…> Task :fileTaskD:\project\gradle-01\src\main\java\com\github\fairy\era\service\IMessageService.javaD:\project\gradle-01\src\main\java\com\github\fairy\era\service\impl\MessageServiceImpl.java-------------------D:\project\gradle-01\src\config\database.propertiesD:\project\gradle-01\src\config\dubbo.propertiesD:\project\gradle-01\src\config\redis.propertiesBUILD SUCCESSFUL in 41ms1 actionable task: 1 executed14:44:34: 执行完成 'fileTask'。
- 在实际的项目开发过程之中,以上配置里面所使用的 sourceSets 环境配置项目,开发中一般都会进行定义。
6.9 文件拷贝
- 通过一系列的操作已经清楚了文件的基本流程,在以后进行项目打包输出控制的时候这样的操作是最为方便的,但是如果要想真正将其应用到项目里面还需要掌握文件拷贝的操作,将 config 目录移动到 src/main 下。

- 修改
build.gradle文件:
sourceSets { // 建立源代码的目录集合main {java {srcDirs = ['src/main/java']}resources {srcDirs = ['src/main/resources', 'src/main/config']}}}task fileTask(type: Copy) { // 定义一个文件拷贝的子任务from 'src/main/config' // [配置文件]定义要拷贝的程序来源from 'src/main/resources' // [配置文件]定义要拷贝的程序来源from 'src/main/java' // [程序文件]编译后的文件内容into 'build/out' // 拷贝的目标路径include '**/*.xml' // 包含的文件类型(匹配后缀)include '**/*.properties' // 包含的文件类型(匹配后缀)exclude '**/*.java' // 不包含源文件}
- 程序执行命令:
gradle fileTask
- 程序执行结果:

- 在日后进行项目打包具体操作的时候,此类的路径的匹配操作一定会在项目中出现,尤其以 dubbo 为主。
