赞
踩
目录
3.2.5 依赖管理-dependencyManagement
今天来学一学Gradle,相比于之前的Maven,现在Gradle可是大名鼎鼎。同样都是项目构建工具,Gradle有什么独特之处?Gradle官网中是这样介绍的
Gradle is an open-source build automation tool focused on flexibility and performance. Gradle build scripts are written using a Groovy or Kotlin DSL. —官网
翻译成中文就是,Gradle 是专注于灵活性和性能的开源构建自动化工具。Gradle 构建脚本是使用 Groovy 或 Kotlin DSL 编写的。
Groovy和DSL都是小语言,用来专门解决某一类任务。
就是许多操作自动化嘛,Maven也行,是一项老技术了。就像写 Java 的时候,如果没有构建工具,我们需要在控制台,通过javac
先将 Java 文件编译为 class 文件,然后再用jar
命令将 class 文件打包为 jar 包。有了自动化构建工具只需要一个命令或是点一个按钮就可以打出 jar包。
Accelerate developer productivity
翻译过来就是:加快开发人员生产力
From mobile apps to microservices, from small startups to big enterprises, Gradle helps teams build, automate and deliver better software, faster.
翻译过来就是:从移动应用程序到微服务,从小型初创公司到大型企业,Gradle 可以帮助团队更快地构建,自动化和交付更好的软件。
Gradle 它汲取了 Ant 和 Maven 的优点,吸收了 Ant 的 task 思想,和 Maven 的规范化和仓库概念。采用 Groovy 或是 Kotlin 语言编写,但是它的代码量更少,可读性更强。
Gradle 具有以下 3 大特性:
Gradle 是一个构建工具,它的构建脚本是基于 Groovy 或是 Kotlin 语言编写的。
Groovy 结合了 Java、Python、Ruby 等当下几大流行语言的优点。它可以说是从 Java 中衍生出来的,为什么这么说呢?因为它的语法和 Java 非常的相似,它的文件也是可以编译为 .class 文件,而且可以使用 Java 的类库。
变量:def
引入包:和Java一样
Tips:在开发 Groovy 时,以下一些库,我们不需要显式的去引入它们,系统已经包含了这些库。
import java.lang.*
import java.util.*
import java.io.*
import java.net.*import groovy.lang.*
import groovy.util.*import java.math.BigInteger
import java.math.BigDecimal
注释和分号:和Java一样
关键字:
大差不差
as | assert | break | case | enum | extends |
---|---|---|---|---|---|
catch | class | const | continue | false | Finally |
def | default | do | else | for | goto |
import | in | instanceof | interface | if | implements |
new | pull | package | return | throws | trait |
super | switch | this | throw | true | try |
while |
在 Java 中我们用单引号(’’)来表示 char,用双引号("")表示字符串。但是在 Groovy 中字符串不仅可以用双引号 (""),而且单引号 (’’),三引号 ("’’")也可以。
- class Example {
- static void main(String[] args) {
- String a = '单引号';
- String b = "双引号";
- String c = '''这是三引号
- Gradle专题
- Groovy语言基础''';
- println(a);
- println(b);
- println(c);
- }
- }
输出结果
单引号
双引号
这是三引号
Gradle专题
Groovy语言基础
我们发现三引号(’’’ ‘’’)其实还可以换行,多行字符串也可以用三引号(’’’ ‘’’)来引用。不像 Java 一样我们如果字符串换行还需要用“ + 和 \n”
连接起来。
所谓插值,就是用 ${变量名}
读取该变量的值,而拼接起来的字符串。
- class Example {
- static void main(String[] args) {
- def a = 'Gradle专题';
- def b = "${a} Groovy语言基础"; //插值字符串 GStringImpl
- println(a.class);
- println(b.class);
- println(b);
- }
- }
class java.lang.String
class org.codehaus.groovy.runtime.GStringImpl
Gradle专题 Groovy语言基础
Groovy 的方法定义跟 Java 比较类似,它的返回类型可以用返回值的类型或是def
定义,也可以使用 public
,static
,private
等修饰。
注意:方法不要定义在 main 方法里面。
if/else
和switch/case
。while
和for
.Tips: 虽然 Groovy 的逻辑控制和 Java 中是一样的,但是 Groovy 又扩展了一些新功能。其中条件语句的
if/else
和循环语句的while
与 Java 中是一样的,但是条件语句的switch/case
和循环语句中的for
, Groovy 在 Java 的基础上做了扩展。
- class Example {
- static void main(String[] args) {
- def x = 0.98
- //def x = 3
- def result
- switch (x){
- case [4,5,6,'Gradle']: //列表
- result = 'list'
- break
- case 3..11:
- result = 'range' //范围
- break
- case Integer:
- result = 'Integer' //类型
- break
- case BigDecimal:
- result = 'BigDecimal'//类型
- break
- default:
- result = 'default'
- break
- }
- println(result)
- };
- }
-
//x = 0.98时输出结果为
BigDecimal
//x = 3时输出结果为
range
相较于 Java 的switch/case
,Groovy 它的判断类型可以是任何类型。
Groovy 除了支持 Java 的for(int i = 0;i < length;i++)
和for(int i :array)
形式的循环语句,还支持以下形式的循环语句:
- class Example {
- static void main(String[] args) {
- //1 对范围的for循环
- def sum = 0
- for (i in 0..100){
- sum += i
- }
- println("0到100的和为:"+sum)
- //2 对List的循环
- def sumList = 0;
- for (i in [1,2,3,4,5,6,7,8,9,10]){
- sumList += i
- }
- println("0到10的和为:"+sumList)
- //3 对Map的循环
- def sumMap = 0
- for (i in ['张三':21,'李四':25,'王五':36]){
- sumMap += i.value
- println i.key
- }
- println("他们的年龄和为:"+sumMap)
- };
- }
-
0到100的和为:5050
0到10的和为:55
张三
李四
王五
他们的年龄和为:82
闭包就是一段用 {} 包起来的代码块,使用方法和方法类型,可以命名,可以传参,可以被调用。
- class Example {
- static void main(String[] args) {
- //1 定义一个闭包
- def closer = {
- println "Gradle专题之Groovy语法"
- }
-
- //2 闭包的两种调用方式
- closer.call()
- closer()
- };
- }
建议大家使用第一种方式去调用,以免和方法的调用混淆。
上面定义的是无参的闭包,下面我们定义一个传参的闭包:
- class Example {
- static void main(String[] args) {
- //1 定义一个传参的闭包
- def closer = {
- String name -> println "${name}专题之Groovy语法"
- }
-
- closer.call('Gradle')
- };
- }
- class Example {
- static void main(String[] args) {
- def filePath = "D:/groovy.txt"
- def file = new File(filePath)
- file.eachLine {
- println it
- }
- };
- }
-
- ----------或是我们也可以像下面这么简洁---------
- class Example {
- static void main(String[] args) {
- def filePath = "D:/groovy.txt"
- def file = new File(filePath)
- println file.text
- };
- }
- class Example {
- static void main(String[] args) {
- def filePath = "D:/groovy.txt"
- def file = new File(filePath)
- file.withPrintWriter {
- it.println("Gradle专题")
- it.println("Groovy语言")
- it.println("文件写入")
- }
- };
- }
常用的主要有:列表,范围,映射。跟 Java 的数据结构比较类似。
- class Example {
- static void main(String[] args) {
- // Java的定义方式
- def list = new ArrayList() //定义一个空的列表
- //groovy中定义
- def list2 = [] //定义一个空的列表
- def list3 = [1,2,3,4] //定义一个非空的列表
-
- println list2.class
- println list3.class
- };
- }
- --------------输出----------------
- class java.util.ArrayList
- class java.util.ArrayList
-
- ----------------------------------
数组:
- //在groovy中使用as关键字定义数组
- def array = [1,2,3,4] as int[]
- //或者使用强类型的定义方式
- int[] array2 = [1,2,3]
- class Example {
- static void main(String[] args) {
- //范围的定义
- def range = 1..15
-
- //范围的使用
- //第一个元素的值
- println ("第一个元素的值:"+range[0])
- //是否包含8
- println ("是否包含8 "+range.contains(8))
- //范围的起始值
- println ("范围的起始值:"+range.from)
- //范围的结束值
- println ("范围的结束值:"+range.to )
- };
- }
-
- --------------输出----------------
- 第一个元素的值:1
- 是否包含8 true
- 范围的起始值:1
- 范围的结束值:15
-
- ----------------------------------
在 Groovy 中定义映射 (MAP) 和 List 类似使用[]
并且要指明它的键 (key)和值 (value),默认的实现类为java.util.LinkedHashMap
.
- class Example {
- static void main(String[] args) {
- //1 映射的定义
- def swordsman = [one:'张三丰',two:'金毛狮王谢逊',three:'张无忌']
-
- //2 映射的使用
- println swordsman['one']
- println swordsman.get('two')
- println swordsman.three
-
- //3 添加元素
- swordsman.four = '成坤'
- println swordsman
-
- //4 groovy中,可以添加一个复杂的元素,比如添加一个map
- swordsman.five = [a:1,b:2]
- println swordsman
- };
- }
-
- ------------------输出----------------------
- 张三丰
- 金毛狮王谢逊
- 张无忌
- [one:张三丰, two:金毛狮王谢逊, three:张无忌, four:成坤]
- [one:张三丰, two:金毛狮王谢逊, three:张无忌, four:成坤, five:[a:1, b:2]]
- --------------------------------------------
def
系统会自动帮我们转换为具体类型;switch/case
支持任意类型的判断;for
支持列表,范围和映射的遍历;as
关键字定义;
重点学习下build.gradle和setting.gradle
需要注意的是,脚本内容的执行是有先后顺序的,一般来说按buildscript->plugins->repositories->dependencies->dependencyManagement。
- buildscript {
- repositories {
- maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
- }
- dependencies {
- classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.4.5'
- }
- }
-
- plugins {
- id 'org.springframework.boot' version '2.4.5'
- id 'io.spring.dependency-management' version '1.0.11.RELEASE'
- id 'java'
- }
-
- group = 'com.zkcloud'
- version = '1.0.0'
-
- repositories {
- maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
- }
-
- ext {
- set('springCloudVersion', "2020.0.2")
- }
-
- dependencies {
- implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
- implementation 'org.springframework.boot:spring-boot-starter-actuator'
- implementation 'com.github.ben-manes.caffeine:caffeine:2.8.8'
- }
-
- dependencyManagement {
- imports {
- mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
- }
- }
-
3.2.1 构建脚本-buildscript
- buildscript {
- repositories {
- /*从哪儿下构建插件*/
- maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
- }
- dependencies {
- /*下什么构建插件*/
- classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.4.5'
- }
- }
其中:repositories
指定仓库的位置,dependencies
指定了插件类型和版本
- plugins {
- id 'org.springframework.boot' version '2.4.5'
- id 'io.spring.dependency-management' version '1.0.11.RELEASE'
- id 'java'
- }
id 'org.springframework.boot' 引入了springboot插件,可执行springboot项目相关的task指令
id 'io.spring.dependency-management' 引入了依赖管理相关的插件,可执行依赖相关的指令
id 'java' 引入了Java插件,就可以支持java编译、运行、打包等task指令
- repositories {
- maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
- }
用于指定项目中的Jar包依赖,需要从哪里下载,由于各种各样的原因,我们需要改成国内的镜像
比如,阿里的镜像 :maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
- dependencies {
- implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
- implementation 'org.springframework.cloud:spring-cloud-starter-config'
- implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'
- implementation 'org.springframework.boot:spring-boot-starter-web'
- implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
- implementation 'org.springframework.boot:spring-boot-starter-jdbc'
- implementation 'com.baomidou:mybatis-plus-boot-starter:3.1.0'
- implementation 'com.alibaba:druid-spring-boot-starter:1.1.9'
- implementation 'org.apache.commons:commons-pool2'
- implementation 'mysql:mysql-connector-java'
- }
显然,是项目中引入外部依赖的关键,类比于maven,可以发现是类似的
implementation 是springboot插件提供的task指令,指定作用域为:从编译、打包到运行的整个过程都有效,类似于maven的scope节点
可以用 groupId artifactId version 指定一个具体依赖
implementation groupId 'com.baomidou' artifactId 'mybatis-plus-boot-starter' version '3.1.0'
也可以用
implementation 'com.baomidou:mybatis-plus-boot-starter:3.1.0'
- dependencyManagement {
- imports {
- mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
- }
- }
这一块主要是依赖管理相关,如果这涉及到,多模块、父子模块,那么在这里,可以界定,全局的依赖版本,记住一点的是,这个地方并不会引入依赖,指定提前界定好,那么在各模块中就不用写版本号了,比如前面说的dependencies里面的依赖,和springboot“同宗同族”的,基本上都没有指定版本,就是因为这里已经指定了springboot的版本,方便依赖的版本管理。
settings.gradle是模块Module配置文件,主要是用于配置子模块,根目录下的setting.gradle脚本文件是针对module的全局配置
- // 为指定父模块的名称 平台根
- rootProject.name = 'project-root'
- //包含子系统以及模块
- include ':project-core'
- //Hello系统模块的加载
- include ':project-hello'
- //World系统模块的加载
- include ':project-world'
初始化阶段
首先解析settings.gradle
Configration阶段:
解析每个Project中的build.gradle,解析过程中并不会执行各个build.gradle中的task
经过Configration阶段,Project之间及内部Task之间的关系就确定了。一个 Project 包含很多 Task,每个 Task 之间有依赖关系。
Configuration会建立一个有向图来描述 Task 之间的依赖关系,所有Project配置完成后,会有一个回调project.afterEvaluate,表示所有的模块都已经配置完了。
The recommended way to execute any Gradle build is with the help of the Gradle Wrapper (in short just “Wrapper”). The Wrapper is a script that invokes a declared version of Gradle, downloading it beforehand if necessary. As a result, developers can get up and running with a Gradle project quickly without having to follow manual installation processes saving your company time and money.—官方
我们翻译过来大致意思就是:官方建议任何 Gradle 构建方法在 Gradle Wrapper 帮助下运行。Gradle Wrapper 它是一个脚本,调用了已经声明的 Gradle 版本,并且我们编译时需要事先下载它。所以,开发者能够快速的启动并且运行 Gradle 项目,不用再手动安装,从而节省了时间成本。
我们可以称 Gradle Wrapper 为 Gradle 包装器,是将 Gradle 再次包装。让所有的 Gradle 构建方法在 Gradle 包装器的帮助下运行。
使用Gradle Wrapper的好处就是方便项目共同开发与管理,在Wrapper中定义好Gradle版本,这样本地没有Gradle也可以来构建项目。
gradle-wrapper.properties
文件指明了 Gradle 的版本号,和 Gradle 运行时的行为属性文件。下面我们具体看下这个文件的内容:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionBase
指定目录的子目录。distributionBase+distributionPath
就是 Gradle 解包后的存放的具体目录;zipStoreBase
指定目录的子目录。zipStoreBase+zipStorePath
就是 Gradle 压缩包的存放位置。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。