赞
踩
目录
学习一个东西的时候,要了解其概念,下面先了解一下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,扩展性和灵活性更高。
为什么学习gradle之前需要学习groovy?
gradle中采用groovy语言作为项目的build脚本,需要我们先大致学习一下groovy,避免在使用gradle构建项目时,看不懂groovy源码,不知道从何下手,比如下面的build.gradle文件,大家可以先试试看是否能看懂和定义呢?
本文章中groovy源码下载地址:
链接:https://pan.baidu.com/s/1MX4_Lk6ynF9waD7XPcG4FQ?pwd=pno3
提取码:pno3
--来自百度网盘超级会员V3的分享
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:
下面我们来创建第一个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)
执行结果如下:
- //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 (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
- 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()
- }
类似于java中的抽象类,可以定义抽象方法,也可以定义非抽象方法(不含方法体)
- trait CarTrait {
-
- run(){
-
- }
-
- abstract stop()
- }
类似于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")
执行结果:
- 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
执行结果:
- 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
执行结果:
- 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()
执行结果:
- 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
运行结果如下:
- //读取文件
- 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")
执行结果:
创建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-6.7-rc-1版本
下载地址:https://services.gradle.org/distributions
在环境变量中配置:GRADEL_HOME
配置path:
验证gradle是否安装成功:
1. 打开idea,new一个新项目
2. 输入包名称、项目名称、版本
3. 点击finish
4. 项目信息介绍
一个project代表一个正在构建的组件(jar/war),当开始构建时,gradle会基于build.gradle实例化出一个Project对象,并通过project来调用其成员。
project中的属性:
Gradle中内置了一些任务,比如build、clean等,也可以自定义任务,语法格式如下:
可以在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中的代码。
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会被依赖进来,这样就存在版本冲突的问题。
通过案例完成多项目构建:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。