Gradle最详细教程,关于Gradle,学习这些就够了.......
目录
Gradle的简介
学习一个东西的时候,要了解其概念,下面先了解一下gradle的相关概念:
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置,面向Java应用为主。当前其支持的语言C++、Java、Groovy、Kotlin、Scala和Swift,计划未来将支持更多的语言。----摘自百度百科
通过对groovy以及gradle的使用和练习后,自我理解与总结如下:
1. gradle类似于maven,是一个集项目jar包管理、依赖管理、项目打包等操作为一体的工具。
2. gradle不同于maven的地方在于,取消maven笨重的xml配置,以独特简便的groovy语言代替大量繁琐的xml配置项。
3. 拥有自己脚本语言的gradle更加灵活,我们可以在项目构建的时候通过groovy语言,去灵活的创建任务,依据自己的需求对项目进行构建,相比于maven来说,使用groovy进行构建的gradle,扩展性和灵活性更高。
Groovy语言的学习
为什么学习gradle之前需要学习groovy?
gradle中采用groovy语言作为项目的build脚本,需要我们先大致学习一下groovy,避免在使用gradle构建项目时,看不懂groovy源码,不知道从何下手,比如下面的build.gradle文件,大家可以先试试看是否能看懂和定义呢?
本文章中groovy源码下载地址:
链接:https://pan.baidu.com/s/1MX4_Lk6ynF9waD7XPcG4FQ?pwd=pno3
提取码:pno3
--来自百度网盘超级会员V3的分享
Groovy环境变量的配置
1. 第一步,下载Groovy,下载地址:https://groovy.apache.org/download.html
2. 下面是小编整理的版本搭配方案:
Groovy | JVM Required (non-indy) | JVM Required (indy) * |
4.0 - current | N/A | 1.8+ |
3.x | 1.8+ | 1.8+ |
2.5 - 2.6 | 1.7+ | 1.7+ |
2.3 - 2.4 | 1.6+ | 1.7+ |
2.0 - 2.2 | 1.5+ | 1.7+ |
1.6-1.8 | 1.5+ | N/A |
1.5 | 1.4+ | N/A |
1.0 | 1.4-1.7 | N/A |
3. 下载完毕后,将zip包解压到本地目录。
4. 下面我们来配置环境变量,点击此电脑鼠标右键,显示出属性,点击高级系统设置,配置GROOVY_HOME
5. 之后在Path变量中配置bin路径:
6. 验证groovy的环境变量是否配置成功,打开黑窗口,输入groovy -version:
第一个Groovy项目
下面我们来创建第一个grovvy项目:
1. 在idea中点击new-project-Groovy-GroovyLibrary,选择groovy的安装目录,点击下一步。
2. 输入项目名称,点击finish
3. 选择项目,点击鼠标右键,new-groovy script,开始第一个groovy程序:
4. 好了,让我们以一句hello world开启groovy的学习之旅吧:
5. 鼠标右键,run,输出:
变量的定义
变量可以通过java中的方式定义,也可以使用def进行定义,需要注意的是:变量在groovy中都是对象类型,没有基本数据类型,就算是定义了基本数据类型,也会自动转换为对象类型,变量的定义方式如下:
//强定义
int a=15
double b=12.3
println "a: "+a
println "a class: "+a.class
println "b: "+b
println "b class: "+b.class
//弱定义
def c=15
def d=11.2
def e="Hello World!"
println "c: "+c
println "d: "+d
println "e: "+e
println "c class: "+c.class
println "d class: "+d.class
println "e class: "+e.class
//弱定义可以修改变量的值
c=10.2
println "c: "+c
println "c class: "+c.class
执行结果如下:
字符串的定义
groovy中的字符串有三种定义方式,分别是:
1. 单引号定义:字符串的格式需要自己控制,比如加转义字符
2. 双引号定义:可扩展字符串
3. 三引号定义:直接在字符串中定义 比如换行直接输入回车即可
代码结构如下:
//字符串的定义方式
//单引号定义
def str1='abc'
//双引号定义
def str2="def"
//双引号可以以这种形式被引用
def str4="ghi${str2}"
//三引号定义
//三引号是带格式的定义,比如输入回车就是换行
def str3='''a
b
c
'''
println "str1: "+str1
println "str2: "+str2
println "str4: "+str4
println "str3: "+str3
执行结果如下:
字符串的常用方法
1. groovy可以调用java中的类库,在java中String拥有哪些方法,groovy中也可以使用哪些方法:
def str1="abc"
println "长度:"+str1.length()
println "是否为空:"+str1.isEmpty()
println "下标对应的字符:"+str1.charAt(0)
def str2="d-e-f"
println "两个字符串是否相等:"+str2.equals(str1)
println "从固定位置截取:"+str2.substring(1)
println "从区间截取:"+str2.substring(0,2)
println "替换字符串:"+str2.replace("-","*")
def str3="g-h-i"
println "str3split : "+str3.split("-")
def str4="jkl"
println "转大写: "+str4.toUpperCase()
def str5="MNO"
println "转小写: "+str5.toUpperCase()
def str6=" pqr "
println "去首尾空格: "+str6.trim()
def str7="a"
def str8="b"
println "比较ASCII码: "+str7.compareTo(str8)
执行结果如下:
流程控制
switch
//a可以是任何类型
def a=1.2
switch (a){
case '123':
println("123")
break;
case [4,7,9]:
println("456")
break;
case 1..20:
println("1..20")
break;
case Integer:
println("Integer")
break;
case BigDecimal:
println("BigDecimal")
break;
default:
println("默认方法")
break;
}
运行结果:
For
//普通for循环
for (int i = 0; i < 3; i++) {
println "普通for循环: "+i
}
//循环list
def list=[1,2,3]
for (i in list){
println "list: "+i
}
//循环范围
for (i in 1..10){
println "循环范围: "+i
}
//循环map
for(i in [1001:"zs",1002:"ls"]){
println "循环map: "+i.key+"----"+i.value
}
执行结果如下:
闭包
groovy中的闭包类似于java8中的lambda表达式,也是对方法的简写。
基本技能
闭包的本质就是一个使用花括号{}包裹起来的代码块。
//定义闭包
def mth1={println "Hello World!"}
//调用闭包
mth1.call()
//在闭包中传入参数
def mth2={str,num->
println "str: "+str+" num: "+num
}
//调用闭包 传参
mth2.call("hello",123)
//闭包定义之省略参数 省略参数时必须使用it作为变量
def mth3={println "hello ${it}"}
//调用闭包 传参
mth3.call(123)
//闭包中定义返回值
def mth4={return "hello ${it}"}
println "闭包中定义返回值: "+mth4.call(123)
执行结果如下:
闭包的使用场景
与基本数据类型结合:
//与基本数据类型配合使用闭包
//定义一个从2递增到10递增的范围
2.upto(10){
println "upto: "+it
}
//使用闭包实现从1加到100
def result=0
1.upto(100){
return result+=it
}
println "result: "+result
//创建递减的范围
10.downto(1){
println "downto: "+it
}
//创建一个执行多少次的闭包
3.times {
println "times: "+it
}
执行结果如下:
与String结合使用:
//配合String使用闭包
def str1="a1b2c3"
//遍历字符串中的每一个字符 返回值是原来的字符串
def str2=str1.each {
println "遍历字符串中的每一个字符: "+it
}
println "返回值是原来的字符串"+str2
//查找符合条件的第一个是数字的值
def str3=str1.find{it->it.isNumber()}
println "查找符合条件的第一个是数字的值: "+str3
//查找符合条件的所有的是数字的值
def str4=str1.findAll{it->it.isNumber()}
println "查找所有的是数字的值: "+str4
//判断任意一个值是否满足条件
def str5=str1.any{it->it.isNumber()}
println "判断任意一个值是否满足条件: "+str5
//判断每一个值是否满足条件
def str6=str1.every {it->it.isNumber()}
println "判断每一个值是否满足条件: "+str6
//对值进行收集 收集后返回值是list
def list=str1.collect {
it->it.isNumber()
}
println "对值进行收集 收集后返回值是list: "+list.toListString()
执行结果如下:
闭包中的变量
This
代表类的实例对象或类本身
Owner
闭包中嵌套闭包时,指向定义它的闭包对象
Delegate
大部分时间和owner一样
一般情况下以上三个变量都是指向当前类对象
//输出闭包中的变量
def mth1={
println "this: "+this
println "owner: "+owner
println "delegate: "+delegate
}
mth1.call()
执行结果:
列表
groovy中的列表默认为linkedlist,定义方式类似于数组。
定义方式
//定义列表
def list=['1','a','b']
println "list: "+list
println "list: "+list.class
//定义数组
def arr1=[1,2,3] as int[]
int[] arr2=[4,5,6]
println "arr1: "+arr1
println "arr2: "+arr2
执行结果:
添加和删除
//操作列表元素
def list1=['1','a','b','c','d','e']
//添加
list1.add(2)
list1.leftShift(3)
list1<<4
println "添加后的list: "+list1
//移除下标为0的元素
list1.remove(0)
//移除元素是d的
list1.removeElement("e")
//按照条件移除 移除下标是偶数的元素
list.remove{it%2==0}
//获取两个list的差
def list2=['1','2','3','4','5']
def list3=['1','2','3']
def list4=list2-list3
println "获取两个list的差: "+list4
执行结果如下:
排序和查找
//排序
def list5=[3,2,5,6,7,4,1,9]
//升序排列
list5.sort()
println "list5.sort: "+list5.toListString()
//按照指定条件排序 降序排序
list5.sort{num1,num2-> num1-num2>0 ? -1:1}
println "list5.sort by rule : "+list5.toListString()
//按照字符串长度排序
def list6=['a','bbb','cc','dddd']
list6.sort{return it.size()}
println "按照字符串长度排序 : "+list6.toListString()
//查找
def list7=[1,2,3,4,5,6]
//查找是偶数的第一个数
println "查找是偶数的第一个数: "+list7.find {it%2==0}
//查找是偶数的所有的数
println "查找是偶数的所有的数: "+list7.findAll {it%2==0}
//查找是偶数的任意数
println "查找是偶数的任意数: "+list7.any {it%2==0}
//判断列表是否全部是偶数
println "判断列表是否全部是偶数: "+list7.every{it%2==0}
//最大值、最小值
println "最大值: "+list7.max()
println "最小值: "+list7.min()
//统计符合条件的偶素有多少个
println "符合条件的值有几个: "+list7.count{it%2==0}
执行结果:
映射map
map的定义和添加
//弱定义map
def map1=[1001:"zs",1002:"ls",1003:"ww",1004:"zl"]
//定义时可省略引号 前提是字符串是key
def map4=[zs:1001,ls:1002,ww:1003,zl:1004]
println "定义map: "+ map1.toMapString()
println "字符串为key时,定义时可省略引号map4: "+ map4.toMapString()
//将map强指引为其他类型的map
HashMap map2=[1001:"zs",1002:"ls",1003:"ww",1004:"zl"]
Hashtable map3=[1001:"zs",1002:"ls",1003:"ww",1004:"zl"]
//添加元素
map1[1005]="迪迦"
println "添加迪迦后: "+ map1.toMapString()
//在map中新增map
map1.'newMap'=[1006:"泰罗",1007:"佐菲"]
执行结果如下:
查找
新建groovy类student:
class Student {
Integer score
String sex
}
在map中新增student对象,并进行查找:
//查找
def map5=[
"张三":new Student(score:70,sex:'男'),
"莉莉":new Student(score:60,sex:'女'),
"小红":new Student(score:59,sex:'女'),
"老王":new Student(score:34,sex:'男')]
//查找map中及格的第一个人
println "查找map中及格的第一个人: "+map5.find {it.value.score>=60}
//查找map中及格的所有的人
println "找map中及格的所有的人: "+map5.findAll {it.value.score>=60}
//查找map中及格的所有的男生
println "找map中及格的所有的人: "+map5.findAll {it.value.score>=60&&it.value.sex=='男'}
//查找map中及格的所有的男生的名字
println "找map中及格的所有的人: "+map5.findAll {it.value.score>=60&&it.value.sex=='男'}.collect {it.key}
//将及格和不及格的分组
println "将及格和不及格的分组: "+map5.groupBy {it.value.score>=60 ? '及格' : '不及格'}
执行结果:
遍历
//遍历
def map6=[
"张三":new Student(score:70,sex:'男'),
"莉莉":new Student(score:60,sex:'女'),
"小红":new Student(score:59,sex:'女'),
"老王":new Student(score:34,sex:'男')]
//方式1
map6.each {println it.key+"*******"+it.value}
//方式2
map6.each {key,value->println key+"*******"+value}
//方式3
map6.eachWithIndex{key,value,index->println key+"*******"+value+"*******"+index}
执行结果:
范围
//定义一个从2到5的范围
def fw1=2..5
println "定义一个从2到5的范围: "+fw1.size()
//定义一个从2到5 不包含5的范围
def fw2=2..<5
println "定义一个从2到5 不包含5的范围: "+fw2.size()
//操作
//获取范围中下标为0的元素
println "获取范围中下标为0的元素: "+fw1[0]
//判断范围是否包含3
println "判断范围是否包含3: "+fw1.contains(3)
//获取范围开始值
println "获取范围开始值: "+fw1.from
//获取范围结束值
println "获取范围结束值: "+fw1.to
执行结果:
面向对象
对象的定义
//创建空构造器的对象
def person1=new Person()
//创建构造器对象
def person2=new Person("张三","男",30)
//指定参数 创建对象
def person3=new Person(name:"张三",sex:"男",age:30)
//声明式
def person4=["王五",20] as Person
Person person5=["王五",20]
//属性取值
println "name:${person3.name} sex:${person3.sex} age:${person3.age}"
println "name:${person3.getName()} sex:${person3.getSex()} age:${person3.getAge()}"
方法的定义调用
//方法的定义和调用
def mth1={
println "mth1"
}
mth1()
def mth2(p1,p2){
println "mth2 p1: "+p1+" p2: "+p2
}
mth2("123","456")
执行结果:
接口
接口的用法和java一致,不再赘述。
interface Car {
run()
}
Trait
类似于java中的抽象类,可以定义抽象方法,也可以定义非抽象方法(不含方法体)
trait CarTrait {
run(){
}
abstract stop()
}
MetaClass
类似于java中的反射机制,通过此方法可以动态的为groovy类添加属性和增加方法:
//动态为类添加没有的属性
Person.metaClass.email="xxx123@qq.com"
def p1=new Person("丽丽","女",28)
println "动态为类添加没有的属性: "+p1.email
//修改属性
p1.email="xxx666@qq.com"
println "动态修改属性: "+p1.email
//动态为类添加方法 将名字大写
Person.metaClass.setNameUpCase={->name.toUpperCase()}
def p2=new Person("lili","女",28)
println "动态为类添加方法 将名字大写: "+p2.setNameUpCase()
//添加静态方法 将名字小写
Person.metaClass.static.setNameLowerCase={String name->name.toLowerCase()}
println "添加静态方法 将名字小写: "+Person.setNameLowerCase("LILI")
执行结果:
Groovy对Json的操作
对象与json之间的转换
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
//将对象转换为json
def p1=new Person("lili","女",28)
//对象转json
def json = JsonOutput.toJson(p1)
println "将对象转换为json: "+json
//将对象列表转换为json
def list=[new Person("lili1","女",28),
new Person("lili2","女",28),
new Person("lili3","女",28),
new Person("lili4","女",28)]
def json1 = JsonOutput.toJson(list)
println "将对象列表转换为json: "+json1
//将json转换为对象
def slurper = new JsonSlurper()
Person text = slurper.parseText(json)
println "将json转换为对象: "+text.class
//将json转换为list
def slurper1 = new JsonSlurper()
def list1 = slurper1.parseText(json1)
println "将json转换为list: "+list1.class
执行结果:
Gson处理json
import com.google.gson.Gson
def p1=new Person("张三","男",30)
//利用Gson转换为json 需要将Gson的jar包导入到项目中
def gson=new Gson()
def json = gson.toJson(p1)
println "对象利用Gson转换为json: "+json
//将list转换为json
def list=[new Person("张三1","男",30),
new Person("张三2","男",30),
new Person("张三3","男",30)]
def ljson = gson.toJson(list)
println "list利用Gson转换为json: "+ljson
//json转对象
def json1 = gson.fromJson(json, Person.class)
println "json转对象: "+json1
//json转list
def json2 = gson.fromJson(ljson, ArrayList.class)
println "json转list: "+json2
println "json转list: "+json2.class
执行结果:
Groovy解析xml
package com.groovy.test01
import groovy.xml.XmlSlurper
import groovy.xml.slurpersupport.GPathResult
final String xml='''
<students>
<student id="1">
<name>张三</name>
<age>28</age>
<sex>男</sex>
<score>65</score>
</student>
<student id="2">
<name>李四</name>
<age>32</age>
<sex>女</sex>
<score>70</score>
</student>
<student id="3">
<name>王五</name>
<age>40</age>
<sex>男</sex>
<score>70</score>
</student>
</students>
'''
//解析xml
def sp=new XmlSlurper()
def text = sp.parseText(xml)
//获取标签内的值
println "解析后的学生姓名: "+text.student[0].name.text()
//获取标签的属性
println "标签的属性: "+text.student[0].@id
//遍历获取的xml值
def list=[]
text.student.each{
it->list.add(it.name.text()+"--"+it.age.text())
}
println "list的值是: "+list.toListString()
执行结果:
Groovy生成xml
import groovy.xml.MarkupBuilder
//生成xml的核心类
def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
//创建根节点
builder.students(){
//创建子节点 小括号里面填写属性
student(id:'1'){
//创建student中的子标签
name('张三')
sex('男')
age(30)
}
//创建子节点 小括号里面填写属性
student(id:'2'){
//创建student中的子标签
name('李四')
sex('男')
age(31)
}
}
println "创建后的xml: "+writer
运行结果如下:
Groovy对文件的操作
//读取文件
def file = new File("f://student.xml")
//遍历文件中的每一行
file.eachLine {println "遍历文件中的每一行: "+it}
//读取文件中的所有的内容
def text = file.getText()
println "读取文件中的所有的内容: "+text
//获取所有的行 返回list
def lines = file.readLines()
println "获取所有的行 返回list: "+lines
//将文件复制到另一个文件中
def copy(String oldPath,String newPath){
//确定目标文件
def file = new File(newPath)
if(!file.exists()){
file.createNewFile()
}
//复制
new File(oldPath).withReader{
def lines = it.readLines()
file.withWriter {
lines.each {
line->it.append(line+"\r\n")
}
}
}
return true
}
copy("f:\\student.xml","f:\\student2.xml")
执行结果:
Groovy把对象写入文件、读取文件中对象
创建Person对象:
class Person implements Serializable{
String name
String sex
Integer age
Person() {
}
Person(String name, String sex, Integer age) {
this.name = name
this.sex = sex
this.age = age
}
}
使用IO流操作对象:
//将对象保存为文件
def saveObject(Object obj,String path){
//将文件封装为对象
def file=new File(path)
if(!file.exists()){
file.createNewFile()
}
file.withObjectOutputStream {
it.writeObject(obj)
}
return true
}
//将文件读取为对象
def readObj(String path){
def obj=null
def file=new File(path)
if(!file.exists()){
return null
}
file.withObjectInputStream {
obj=it.readObject()
}
return obj
}
//创建对象
def person = new Person()
//将对象写入文件
println saveObject(person,"f:\\person.txt")
//将文件读取为对象
println readObj("f:\\person.txt")
执行结果如下:
Gradle的学习和使用
下载和安装
这里推荐gradle-6.7-rc-1版本
下载地址:https://services.gradle.org/distributions
环境变量配置
在环境变量中配置:GRADEL_HOME
配置path:
验证gradle是否安装成功:
创建第一个gradle项目
1. 打开idea,new一个新项目
2. 输入包名称、项目名称、版本
3. 点击finish
4. 项目信息介绍
构建脚本介绍
Project
一个project代表一个正在构建的组件(jar/war),当开始构建时,gradle会基于build.gradle实例化出一个Project对象,并通过project来调用其成员。
project中的属性:
Task
Gradle中内置了一些任务,比如build、clean等,也可以自定义任务,语法格式如下:
定义task的常用方法:
可以在build.gradle中定义task
task task1,{
println "task1"
doFirst {
}
doLast{
}
}
定义完毕后在右侧可以看到任务名称,点击后可以执行任务:
这里的任务默认出现在other下,如果我们需要定义任务分组的话按照如下形式定义:
task task1,{
println "task1"
group("MyTask")
doFirst {
}
doLast{
}
}
定义多个任务
tasks{
task task2{
group("MyTask")
println "task2"
}
task task3{
group("MyTask")
println "task3"
}
}
任务依赖
使用dependsOn关键字实现任务依赖:
task task1,{
println "task1"
group("MyTask")
doFirst {
}
}
task task4,{
println "task1"
group("MyTask")
dependsOn 'task1'
doFirst {
}
}
task task5(dependsOn:task4){
println "task1"
group("MyTask")
dependsOn 'task1'
doFirst {
}
}
任务的生命周期
Gradle的生命周期分三个阶段:初始化阶段、配置阶段、执行阶段。
初始化阶段
通过settings.gradlle判断有哪些项目需要初始化,加载所有需要初始化的项目的build.gradle文件 并为每个项目创建project对象
配置阶段
执行各项目下的build.gradle脚本,完成project的配置,并且构造Task任务依赖关系图以便在执行 阶段按照依赖关系执行Task中的配置代码
执行阶段
通过配置阶段的Task图,按II贿执行需要执行的任务中的动作代码,就廠行任务中写在doFirst或 doLast中的代码。
新建插件,把一个项目打成jar包,发布到maven仓库给另一个项目使用
1. 新建gradle java项目。
2. 在新的gradle java项目的build.gradle文件中配置如下信息:
id 'java-library'//配置此项表示项目可以打包为jar给其他项目使用
id 'maven-publish'//将打包的项目发布到maven仓库中
3. 在新的gradle java项目的build.gradle文件中新增插件,将打包好的项目发布到maven本地仓库中:
//发布插件 将打包的项目发布到maven本地仓库
publishing{
//配置发布动作
publications{
maven(MavenPublication){
from components.java
}
}
//配置发布到本地maven库中
repositories {
mavenLocal()
}
}
4. 先在项目中建一个类,然后执行build,build完毕后点击publish,此时jar包就打包到本地的maven仓库中了。
5. 打开本地仓库,查看maven-metadata-local.xml,有jar包相关的信息,在另一个项目中直接进行引用即可使用此jar包。
6. 在另一个项目中进行引用,build.gradle文件中的配置如下:
//引入另一个jar包
compile group: 'com.test', name: 'JarGradle', version: '1.0-SNAPSHOT'
mavenLocal()//先从maven本地仓库中找
7. 引用一下jar测试完成
版本冲突的解决方案
(1)依赖传递性:
假设你的项目依赖于一个库,而这个库又依赖于其他库。你不必自己去找出所有这些依赖,你只需 要加上你直接依赖的库,Gradle会隐式的把这些库间接依赖的库也加入到你的项目中。
(2)传递性做中版本冲突:
由于传递性依赖的特点,两个不同版本的jg会被依赖进来,这样就存在版本冲突的问题。
多项目构建案例
通过案例完成多项目构建:
更多推荐
所有评论(0)