1.Gradle入门
Gradle是一个非常优秀的构建系统工具,它的DSL基于Groovy实现。
1.1 配置Gradle环境
grdle需要Java环境,要求JDK 6 以上,并且要配置Java的环境变量。
Gradle文件说明
官网下 https://gradle.org/ 载,得到压缩包 gradle-2.14.1-all.zip 。然后解压。得到目录清单
1.docs API DSL 指南文档
2.getting-started.html
3.init.d gradle初始化脚本目录
4.lib
5.LICENSE
6.media icon 资源
7.NOTICE
8.sample 示例
9.src 源文件
然后把GRADLE_HOME/bin添加环境变量路径里。
执行:
gradle -v 可以查看是否安装成功。
如果要在AS里执行,记得重启AS.
task hello{
doLast{
println "hello world"
}
}
执行命令:gradle -q hello
-q 参数用于控制gradle输出的日志级别
1.2.Gradle Wrapper
是对gradle的包装,便于团队开发过程中统一Gradle构建的版本。这样大家可以使用统一的Gradle版本进行构建。wrapper在window下一个处理脚本,在linux下是一个shell脚本。他会检查Gradle有没有被下载关联。
- 生产wrapper
gradle提供了内置的Wrapper Task帮助我们自动生成Wrapper所需的文件目录。在一个项目的根目录输入gradle wrapper即可生成。
gralde wrapper
distributionBase=GRADLE_USER_HOME 主目录
distributionPath=wrapper/dists 相对distributionBase的路径
zipStoreBase=GRADLE_USER_HOME 同distributionBase
zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-6.5-bin.zip Gradle发行版压缩包的下载地址。
1.3.自定义Wrapper
gradle-wrapper.properties由wrapper task生产的。我们可以自定义wrapper task任务来达到配置gradle-wrapper.properties。
task wrapper(task:Wrapper){
gradleVersion = '2.4'
}
distributionBase=GRADLE_USER_HOME
//下载gradle的路径
distributionUrl=https://services.gradle.org/distributions/gradle-6.7.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
1.4 gradle 日志
ERROR
QUIET
WARNING
LIFECYCLE 进度消息
INFO
DEBUG
输入Quiet级别之上的日志
gradle -q tasks
a 错误堆栈信息
默认情况下,堆栈信息是关闭的。需要我们通过命令行的堆栈信息开关打开它。
-s or --stacktrace 输出关键性信息
-S or --full-stacktrace 输出详细信息
b logger. 日志调试
logger.quiet("")
logger.error("")
1.5 gradle 命令行
./gradlew 是Mac的命令,如果你是window,输入gradle
使用帮助
./gradlew -?
./gradlew -h
./gradlew -help
强制刷新依赖
./gradlew --refresh-dependencies assemble
多任务调用
有时候我们要同时运行多个任务,比如执行jar之前,先clean
./gradlew clean jar
通过任务名字缩写执行
比如有个任务connectCheck
可以执行:
./gradlew cc
2.Groovy基础
Groovy是基于JVM的一种动态语言,Groovy完全兼容Java,有在此增加很多动态类型和灵活的特性。如 闭包 DSL
2.1 字符串
Groovy不需要分号,单引号和双引号都可以。
单引号没有运算能力,表示常量字符串。双引号可以直接运行表达式计算。
2.2 集合
Groovy完全兼容Java的集合,且进行了扩展。
list set map Queue
list
def numlist = [1,2,3,4] 使用索引访问集合
map
def map = ['width':1024,'height':768]
println map['width']
map.each{
println "key:${it.key},Value:${it.value}"
}
2.3 方法
def method(int a,int b){
println a+b
}
task invokeMethod<<{
method(1,2)
}
return 可以不写
代码块是可以作为参数传递的
2.4 JavaBean
class Person{
private String name
}
task hellJava <<{
person p = new Person()
p.name ="lisi"
println "名字是:${p.name}"
}
2.5 闭包
闭包就是一段代码块
task helloClosure<<{
customEach{
print it
}
}
//closure参数用于接收闭包(代码块)
def customEach(closure){
for (i in 0..<10) {
closure(i)
}
}
传递参数
我们为闭包传递了两个参数,key .value
task helloClosure {
eachmap {
K, V ->
println "$K $V"
}
}
def eachmap(closure) {
def map = ["one": 1, "two": 2]
map.each {
closure(it.key, it.value)
}
}
闭包委托
闭包的强大之处在于支持闭包方法的委托。Groovy的闭包有thisObject、owner、delegate三个属性。
当你在闭包内调用方法时,有它们来确定使用哪个对象来处理。默认delegate/owner是相等的。但是delegate可以被修改的。Gradle中的闭包的很多功能都是通过修改delegate实现的。
task helloDelegate {
new Delegate().test {
println "thisObject:${thisObject.getClass()}"
println "owner:${owner.getClass()}"
println "delegate:${delegate.getClass()}"
method1()
it.method1()
}
}
def method1() {
println "context this:${this.getClass()} in root"
println "method1 in root"
}
class Delegate {
def method1() {
println "Delete this:${this.getClass()} in Delegate"
println "method1 in Delegate"
}
def test(Closure<Delegate> closure) {
closure(this)
}
}
result:
thisObject:class build_9eq7gfn6et0rl6qz17rvoqogw
owner:class build_9eq7gfn6et0rl6qz17rvoqogw$_run_closure2
delegate:class build_9eq7gfn6et0rl6qz17rvoqogw$_run_closure2
context this:class build_9eq7gfn6et0rl6qz17rvoqogw in root
method1 in root
Delete this:class Delegate in Delegate
method1 in Delegate
thisObject的优先级最高。默认情况下,优先使用thisObject来处理闭包中调用的方法,如果有则执行。thisObject其实就是这个构建脚本的上下文,它和脚本中的this对象是相等的。
列子中也证明delegate和owner是相等的,两个的优先级是:owner比delefate高。所以闭包内方法的处理顺序是:thisObject>owner>delegate。
2.6 DSL 领域特定语言
DSL (domain specific Language)领域特定语言。专注某个领域的语言。Gradle就是一个DSL.基于Groovy,专门解决自动化构建的DSL.
3.Gradle构建基础
3.1 setting文件
用于初始化及工程树配置。为了配置子工程。
子工程只有在settting文件里配置了才能识别、
3.2 build.gradle文件
每个project都会有一个build.gradle文件,它是project构建入口,配置版本,依赖库,配置插件。
Root Project也可以获取所有child project,比如Java在开发大型项目的时候,会有很多模块,每个模块都是project。
subprojects {
apply plugin "java"
repositories {
jecenter()
}
}
}
3.3 projects 及Tasks
gradle中,可以有很多project,可以定义project生成jar,生成war包,也可以创建project用于上传war文件。一个project又包含多个task。
task是一个操作,一个原子性操作。比如打个jar包,复制一分文件,编译一次Java代码
task xxxx{
doOne{
println 'hello'
}
}
3.4 创建一个任务
task customTask1{
doFirst{
println "this is task"
}
doLast{
println "this is last"
}
}
task是一个关键字,它是project对象的一个函数,原型为create(String name,Closure configureClosure),customTask1是任务的名字;第二个参数是闭包,大括号里的代码。
tasks.create("customTask2"){
doFirst {
println "one"
}
doLast {
println "two"
}
}
3.5 任务依赖
dependsOn是Task类的一个方法,可以接收多个依赖的任务作为参数。
task hello {
println "hello"
}
task exMain (dependsOn:hello){
doLast {
println "main"
}
}
还可以依赖多个task
task exMain (){
dependsOn hello,world
doLast {
println "main"
}
}
3.7 自定义属性
project和Task 都可以让用户添加额外的自定义属性,使用ext
ext.name = 'lisi'
ext{
phone =890
address = 'hello'
}
task one{
println "$name"
println "$phone"
}
自定义属性还可以使用在sourceSet中,
sourceSets.all{
ext.resourceDir = null
}
sourceSets{
main{
resourcesDir ='/main'
}
test{
resourcesDir ="/test"
}
}
4.Gradle 任务
1.多种方式创建任务
依赖于project给我们提供的快捷方法及TaskContainner提供的相关Create方法,可以有多种方式来创建任务。
def Task createTask = task(createTask)
createTask.doLast {
println "hello world"
}
createTask就是任务名字,可以使用.gradlew createTask 来执行这个任务。这种方式的创建其实调用project对象中的task(String name)的方法
第二种方式 以一个任务名字+ 一个对该任务配置的map对象来创建任务。
def Task createTask2 = task(createTask2,group: BasePlugin.BUILD_GROUP)
第三种:任务+闭包
task createTask3{
decription "演示"
doLast {
println "this is task + closure style"
}
}
2.多种方式访问任务
我们创建的任务都会作为项目(project)的一个属性,属性名就是任务名,可以直接通过该任务名字访问和操作该任务;
其次,任务都是通过TaskContainer创建的,它是我们创建任务的集合,在project中我们通过tasks属性访问TaskContainer.访问的时候,任务名就是key
再则,通过路径访问,一个是get 一个是find,区别为get的时候如果找不到会抛出异常UnknowTaskException。而find找不到返回null。
通过名称访问,也有get 和find 两种,区别和上述一样。
3.任务分组和描述
任务分组就是分类,便于对任务进行归类整理。任务的描述就是说明这个任务有什么作用。
4.<< 操作符
<< 操作符在gradle的task是doLast的短标记形式。
5.任务的执行分析
当我们执行一个Task的时候,其实就是执行其拥有的actions列表,这个列表保存在Task对象实例中的actions成员变量中,其类型是一个List
List<ContextAwareTaskAction> actions = new ArrayList<>()
我们把task之前执行、task本身执行、task之后执行分别称为doFirst 、doSelf、doLast
Task task = task two(type: CustomTask)
task.doFirst {
println '之前执行'
}
task.doLast {
println '之后执行'
}
class CustomTask extends DefaultTask {
@TaskAction
def doSelf() {
println 'task 自身执行'
}
}
6.任务排序
通过shouldRunAfter和mustRunAfter这两个方法,可以控制一个任务应该或者一定在某个任务之后执行,你可以控制任务的执行顺序,而不是通过强依赖的方式。
taskB.shouldRunAfter(taskA) 表示taskB 应该在taskA执行之后执行,这里的应该不是必须,有可能任务顺序不能按照预期完成。而mustRunAfter(taskA) 表示严格执行。
7.任务的启用和禁用
Task中有个enable属性,用于启用和禁用任务。默认true,表示启用。
8.任务的OnlyIf断言
断言就是一个条件表达式,Task有一个onlyif方法,接受一个闭包作为参数。如果该闭包返回ture表示任务执行。否则跳过。
9.任务规则
我们创建的任务都有TaskContainer进行管理,所以当我们访问任务的时候都是通过TaskContainner进行访问,而TaskContainner继承NamedDomainObjectCollection,所以任务规则其实就是NamedDomainObjectCollection的规则