一、构建块
1.每个构建块都包含三个基本构建块:project、task和property;
2.每个构建块包含至少一个project,进而又包含一个或多个task;
3.project和task暴露的属性可以用来控制构建快;
二、项目
1.一个项目(project)代表一个正在构建的组件(比如,一个JAR文件),或一个想要完成的目标,如部署应用程序;
2.每个Gradle构建脚本至少定义一个项目,当构建启动后,Gradle基于build.gradle中的配置实例化org.gradle.api.Project类,并且能够通过project变量使其隐式可用;
3.一个project可以创建新的task,添加依赖和配置,并应用插件和其它构建脚本;
//不显式使用project变量的情况设置项目描述
setDescription("myProject");
//在不使用project变量的情况通过Groovy语法类访问name和description属性
println "Description of project $name:" + project.description
三、任务
1.Task的一些重要功能:任务动作(task action)和任务依赖(task dependency);
2.任务定义了一个当任务执行时最小的工作单元,可以简单到只打印“Hello world!”,或复杂到编译Java源代码;
四、属性
1.每个Project和Task实例都提供了可以通过getter和setter方法访问的属性;
2.一个属性可能是一个任务的描述或项目的版本;
3.扩展属性:Gradle的很多领域模型提供了特别的属性类型,在内部以键值对的形式存储;
//只在初始生命扩展属性时需要ext命令空间
project.ext.myPro = 'myValue'
ext {
someOtherProp = 123
}
//使用ext命令控件访问属性是可选的
assert myProp == 'myValue'
println project.someOtherProp
ext.someOtherProp = 567
4.Gradle属性:
Grale属性可以通过在gradle.properties文件中声明直接添加到项目中,这个文件位于<USER_HOME>/.gradle目录或项目目录下,这些属性可以通过项目实例访问。
即使你有多个项目,每个用户也只能有一个Gradle属性文件在<USER_HOME>/.gradle目录下。
gradle.properties文件:
examplePro = myValue
someOtherProp = 455
可以通过如下方式访问项目两个变量:
assert project.exampleProp == 'myValue'
task printGradleProperty << {
println "Second property:$someOtherProp"
}
5.声明属性的其它方式:Gradle也提供了很多其它方式为构建提供属性,比如:
项目属性通过-P命令行选项提供;
项目属性通过-D命令行选项提供;
环境变量按照下面的模式提供:ORG_GRADLE_PROJECT_propertyName=someValue
五、使用Task
1.声明task动作:
动作(action)就是在task中合适的地方放置构建逻辑;
Task接口提供了两个不相关的方法来声明task动作:doFirst(Closure)和doLast(Closure);
当task被执行的时候,动作逻辑被定义为闭包参数一次执行;
version = '1.0-SNAPSHOT'
//声明一个包含doFirst和doLast的task
task printVersioin {
doFirst {
println "Before reading the project version"
}
doLast {
println "Version: $version"
}
}
//在动作列表的开始添加doFirst闭包
printVersion.doFirst { println "First action" }
//使用doLast别名在动作列表的最后添加闭包
printVersion << { println "Last action" }
六、访问Default属性
task printVersion << {
logger.quiet "Version: $version"
}
//在创建task时候,为这两个属性设置值作为参数
task printVersion(group: 'versioning', description: 'Prints project version.') << {
logger.quiet "Versioin: $version"
}
task printVersion {
//通过getter和setter方法来设置属性
group = 'versioning'
description = 'prints project version.'
doLast {
logger.quiet "Version: $version"
}
}
七、定义Task依赖
1.dependsOn方法允许声明一个或多个task,下面清单显示了使用dependsOn方法应用task依赖的不同方式:
build.gradle文件:
task first << { println "first" }
task sencond << { println "second"}
//指定多个task依赖
task printVersion { dependsOn: [second, first] } << {
logger.quiet "Version:$version"
}
task third << { println "third" }
third.dependsOn{ 'printVersion ' }
运行构建:
C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_01-task-dependencies>gradle -q third
first
second
Version: 0.1-SNAPSHOT
third
2.Gradle的思想是声明在一个给定的task之前什么该执行,而没有定义他该如何执行;
3.在Gradle中,执行顺序是由task的输入/输出规范自动确定的:
一方面,不需要知道整个task依赖链上的关系是否发生改变;
另一方面,因为构建没有严格的执行顺序,也就是支持task的并行执行,这样可以极大的节约构建执行时间;
八、终结器task
在实践中,你会发现所依赖的task执行后需要清理某种资源,典型的例子就是Web容器需要对已经部署的应用程序进行集成测试。
1.终结器task:即使终结task失败了,Gradle的task也会按预期运行;
build.gradle文件:
task first << { println "first" }
task second << { println "second" }
//声明一个task被另一个task终结
first.finalizedBy second
运行脚本: C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\finalizer-task>gradle -q first
first
second
九、添加任意代码
1.通过POGO来表示项目的版本:
build.gradle文件:
//根据java.lang.Object表示的version属性;Gradle总是调用toString()来获取version的值
version = new ProjectVersion(0, 1)
class ProjectVersion {
Integer major
Integer minor
Boolean release
ProjectVersion(Integer major, Integer minor) {
this.major = major
this.minor = minor
this.release = Boolean.FALSE
}
ProjectVersion(Integer major, Integer minor, Boolean release) {
this(major, minor)
this.release = release
}
@Override
String toString() {
//只有当release属性值为false的时候,版本上才会添加-SNAPSHOT后缀
"$major.$minor${release ? '' : '-SNAPSHOT'}"
}
}
task printVersion << {
logger.quiet "Version: $version"
}
运行构建:
C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_02-project-version-pogo>gradle printVersion
:printVersion
Version: 0.1-SNAPSHOT
BUILD SUCCESSFUL
十、理解task配置
1.Task定义没有使用左移操作符(<<),Gradle称之为task配置;
2.task配置块永远在task动作执行之前被执行;
version.properties文件:
major=0
minor=2
release=false
build.gradle文件: //Project接口提供了file方法;它会创建一个相对于项目目录的java.io.File实例
ext.versionFile = file('version.properties')
//没有使用左移操作符定义task配置
task loadVersion {
project.version = readVersion()
}
ProjectVersion readVersion() {
logger.quiet 'Reading the version file.'
//如果版本文件不存在,将抛出GradleException异常,带有相应的错误消息
if (!versionFile.exists()) {
throw new GradleException("Required version file does not exist: $versionFile.canonicalPath")
}
Properties versionProps = new Properties()
//Groovy的文件实现通过添加新的方法来读取InputStream
versionFile.withInputStream { stream ->
versionProps.load(stream)
}
//在Groovy中,如果return是方法中最后一条语句的话,则可以省略它
new ProjectVersion(versionProps.major.toInteger(), versionProps.minor.toInteger(), versionProps.release.toBoolean())
}
task printVersion << {
logger.quiet "Version: $version"
}
class ProjectVersion {
Integer major
… …
}
执行构建: C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_03-configuration-task>gradle printVersion
Reading the version file.
:printVersion
Version: 0.2-SNAPSHOT
BUILD SUCCESSFUL
Total time: 3.552 secs
3.无论什么时候执行Gradle构建,都会运行三个不同的生命周期阶段: 初始化阶段:Gradle为项目创建了一个Project实;
配置阶段:适合于项目或指定task设置所需的配置,项目每一次构建的任何配置代码都可以被执行-即使你只执行gradle tasks;
执行阶段:所有task都应该以正确的顺序执行,执行顺序由它们依赖决定的,如果任务被认为没有修改过,将被跳过;
十一、声明task的inputs和outputs
1.Gradle通过比较两个构建task的inputs和outputs来决定task是否是最新的,只有当inputs和outputs不同时,task才运行,否则将跳过;
version.properties文件:
major=0
minor=1
release=true
build.gradle文件: ext.versionFile = file('version.properties')
task loadVersion {
project.version = readVersion()
}
ProjectVersion readVersion() {
… …
}
task makeReleaseVersion(group: 'versioning', description: 'Makes project a release version.') {
//在配置阶段声明inputs/outputs
//声明版本的release属性作为输入
inputs.property('release', version.release)
//由于版本文件被修改了,所以它被声明作为输出文件属性
outputs.file versionFile
doLast {
version.release = true
//Ant task的propertyfile提供了一个遍历的方式来修改属性文件
ant.propertyfile(file: versionFile) {
entry(key: 'release', type: 'string', operation: '=', value: 'true')
}
}
}
class ProjectVersion {
… …
}
运行构建:
C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_05-task-inputs-outputs>gradle makeReleaseVersion
Reading the version file.
:makeReleaseVersion
BUILD SUCCESSFUL
Total time: 4.775 secs
//Gradle已经知道项目版本被设置为发布版本,而且自动跳过task的第二次执行
C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_05-task-inputs-outputs>gradle makeReleaseVersion
Reading the version file.
:makeReleaseVersion UP-TO-DATE
BUILD SUCCESSFUL
Total time: 3.457 secs
十二、编写和使用自定义的Task
1.自定义Task包含两个组件,自定义的task类,封装了逻辑行为,也被称作任务类型;
2.真实的task,提供了用于配置行为的task类所暴露的属性值;
3.可维护性是编写自定义task类的优势之一,增强的task的优点是可重用性;
version.propertioes文件:
#Mon, 08 Apr 2013 06:40:21 -0400
major=0
minor=1
release=true
build.gradle文件: ext.versionFile = file('version.properties')
task loadVersion {
project.version = readVersion()
}
ProjectVersion readVersion() {
… …
}
//创建一个ReleaseVersionTask类型的task,并通过它的属性赋值来设置输入和输出
task makeReleaseVersion(type: ReleaseVersionTask) {
release = version.release
destFile = versionFile
}
//编写一个继承Gradle默认task实现的自定义task
class ReleaseVersionTask extends DefaultTask {
//通过注解声明task的输入/输出
@Input Boolean release
@OutputFile File destFile
//在构造器中设置task的group和description属性
ReleaseVersionTask() {
group = 'versioning'
description = 'Makes project a release version.'
}
//使用注解声明将被执行的方法
@TaskAction
void start() {
project.version.release = true
ant.propertyfile(file: destFile) {
entry(key: 'release', type: 'string', operation: '=', value: 'true')
}
}
}
class ProjectVersion {
… …
}
执行构建: C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_07-custom-task-usage>gradle makeReleaseVersion
Reading the version file.
:makeReleaseVersion
BUILD SUCCESSFUL
Total time: 4.887 secs
C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_07-custom-task-usage>gradle makeReleaseVersion
Reading the version file.
:makeReleaseVersion UP-TO-DATE
BUILD SUCCESSFUL
Total time: 3.45 secs
十三、应用自定义task的可重用性
project-version.properties文件:
#Mon, 04 Jan 2016 00:51:46 +0800
major=0
minor=1
release=true
build.gradle文件: ext.versionFile = file('project-version.properties')
task loadVersion {
project.version = readVersion()
}
ProjectVersion readVersion() {
… …
}
//为makeReleaseVersion task设置单独的属性值
task makeReleaseVersion(type: ReleaseVersionTask) {
//POGO版本表示使用prodReady属性来指示发布标识
release = version.prodReady
//指定不同的版本文件对象
destFile = new File('project-version.properties')
}
class ReleaseVersionTask extends DefaultTask {
@Input Boolean release
… …
}
//在另一个项目中不同的POGO暴露不同的属性
class ProjectVersion {
Integer min
Integer maj
Boolean prodReady
@Override
String toString() {
"$maj.$min${prodReady ? '' : '-SNAPSHOT'}"
}
}
执行构建: C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_09-custom-task-reusability>gradle makeReleaseVersion
Reading the version file.
:makeReleaseVersion
BUILD SUCCESSFUL
Total time: 4.875 secs
C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_09-custom-task-reusability>gradle makeReleaseVersion
Reading the version file.
:makeReleaseVersion UP-TO-DATE
BUILD SUCCESSFUL
Total time: 3.448 secs
十四、Gradle的内置task类型
1.一个好的回滚策略是必须的,保留一份最新的稳定的应用程序可交付版本的备份非常重要!
2.你想要执行的task顺序:
make ReleaseVersion->war->create Distribution->backup ReleaseVersion->release
3.task依赖推断:通过使用一个task的输出作为另一个task的输入,Gradle就可以判断出依赖关系了;
build.gradle文件:
apply plugin: 'war'
ext.versionFile = file('version.properties')
task loadVersion {
project.version = readVersion()
}
ProjectVersion readVersion() {
… …
}
task makeReleaseVersion(group: 'versioning', description: 'Makes project a release version.') << {
version.release = true
ant.propertyfile(file: versionFile) {
entry(key: 'release', type: 'string', operation: '=', value: 'true')
}
}
task createDistribution(type: Zip, dependsOn: makeReleaseVersion) {
//隐式引用War task的输出
from war.outputs.files
//把所有源文件都放到ZIP文件的src目录下
from(sourceSets*.allSource) {
into 'src'
}
//为ZIP文件添加版本文件
from(rootDir) {
include versionFile.name
}
}
task backupReleaseDistribution(type: Copy) {
//隐式引用createDistribution的输出
from createDistribution.outputs.files
into "$buildDir/backup"
}
task release(dependsOn: backupReleaseDistribution) << {
logger.quiet 'Releasing the project...'
}
class ProjectVersion {
… …
}
执行构建: C:\Users\chengxiang.peng.QUNARSERVERS\GradleSources\gradle-in-action-source\chap
ter04\listing_04_10-built-in-tasks>gradle release
Reading the version file.
:makeReleaseVersion
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:war
:createDistribution
:backupReleaseDistribution
:release
Releasing the project...
BUILD SUCCESSFUL
Total time: 4.853 secs