Gradle入门笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle入门笔记相关的知识,希望对你有一定的参考价值。

      引言:Gradle是一种构建工具,它抛弃了基于XML的构建脚本,取而代之的是采用一种基于Groovy的内部领域特定语言。

 

      Groovy是一种基于JVM的敏捷开发语言,其开发效率比java高,但对比特殊的编译性语言Java( Java文件将编译成JVM可辨识的二进制文件.class )groovy作为一个动态的脚本语言,由于元编程特性(元编程简单来说就是,编写运行时操作语言构建的代码,用代码操作代码)groovy对比java效率低。下图为groovyjavademo效率对比图:

  技术分享

             附上对比图来源链接:https://dzone.com/articles/java-7-vs-groovy-21
 
      尽管Groovy效率比java低,Groovy的开发效率及其基于JVM带来的跨平台性的优势却不可忽视,同时Gradle是为Java项目服务,考虑至此,Gradle开发团队选用了Groovy为开发语言(个人理解)。
下面才是gradle的官方解释(=_=!!):
      "我们认为在脚本构建时,内部基于 XML 的 DSL(基于一个动态语言)优势是巨大的. 有许多动态语言在那里, 我们为什么选择 Groovy? 答案在于 Gradle 的运行环境. 虽然 Gradle 是以一个多用途的构建工具为核心,它的重点是Java项目. 在这样的项目中, 显然团队每个成员都了解 Java. 我们认为构建应尽可能对所有团队成员都是透明的, 所以选择了 Groovy.
      你可能会说,为什么不直接使用 Java 作为构建脚本的语言. 我们认为这是一个有效性的问题. 对于你的团队, 它要有最高的透明度和最低的学习曲线, 也就是说容易掌握. 但由于 Java 的限制, 这样的构建语言不会那么完美和强大. 如 Python,Groovy 或 Ruby 语言都可以有更高的效率. 我们选择了 Groovy 是因为它给 Java 开发人员提供了迄今为止最大的透明度. 其基本的符号和类型与 Java 是一样的,其封装结构和许多其他的地方也是如此.
      对于那些同样分享 Python 或 Ruby 知识的 Java 团队将会很乐意学习它. Gradle 的设计非常适合在 JRuby 和 Jython 中创建另一个构建脚本引擎. 它只是目前开发的优先级里. 我们十分支持任何人来做贡献, 创建额外的构建脚本引擎."
 
     在理解Gradle是干什么之前,先去粗略了解重温一下几个插件工具:
1. Apache Ant:是一个将软件编译测试部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发
2.Apache Ivy:Apache Ant 下的一个子项目,Apache Ivy是一个优秀的管理(记录、跟踪、解析和报告)项目依赖的工具,提供了强大的依赖管理功能,可与Apache Ant紧密集成。可以说ant负责项目的build,而Ivy负责项目内部的依赖。
3.Apache Maven:模块化项目构建工具(Building a Project )。它能够管理依赖、构建周期、测试、打包并且在仓库中发布你的制品。同时拥有了ant与ivy的功能。
 
     前面啰嗦了一大推,把Groovy,Apache ant,Apache ivy,Apache maven都提了一遍,就是为了现在总结使用Gradle的优势(以下摘抄修改自维基百科---Gradle)
  • 自动处理包相依关系 - 取自 Maven Repos , Ivy 的概念
  • 自动处理布署问题 - 取自 Ant 的概念
  • 条件判断写法直觉 - 使用 Groovy 语言(简单理解动态脚本语言,开发效率高)
 
      过去 Java 开发者常用 Maven 和 Ant 等工具进行封装布署的自动化,或是两者兼用,不过这两个包彼此有优缺点,如果频繁改变相依包版本,使用 Ant 相当麻烦,如果琐碎工作很多,而Maven 功能不足,且两者都使用 XML 描述,相当不利于设计 if、switch 等判段式,即使写了可读性也不佳,在我们团队开发中,基本都使用了Maven管理依赖,而由于历史问题,项目中的依赖多多少少存在不合理的地方,修改起来怕是动一发而牵全身,而 Gradle 改良了过去 Maven、Ant 带给开发者的问题,功能更全,使用便更加灵活,为此,这也正是我所在开发团队一起学习Gradle的原因与动力。
     
      
      以下正式开始学习如何搭建第一个使用Gradle的java项目
 

Gradle安装

基于开发团队日常基本是使用windows操作系统开发,因此介绍此笔记暂时基于windows而写。
 
Gradle的安装条件:JDK6及以上(Gradle自带Groovy库,Gradle会忽略此前安装的Groovy)。
 
1. 总得先下载Gradle先吧,点击这里 http://www.gradle.org/downloads 。很慢?对的,很慢。 考虑到官网下载速度很慢很龟速,我特意把gradle-3.4放上oss中。
 
2.下载完后,在指定路径解压,添加一个 GRADLE_HOME 环境变量来指明 Gradle 的安装路径,再添加 %GRADLE_HOME%/bin 到 PATH 环境变量中.。正常的话,现在就可以运行Gradle了。测试是否成功安装配置的方法是,直接上图吧。
技术分享

 

 
     跳过最简单的HelloWorld的demo,我们直接跑起一个spring boot的多项目的build。
网上的教程,乃至官方文档在建立项目介绍上是选择跳过的,因此一开始,我查看了很多教程都是模模糊糊的,教程中都是在build.gradle中写上applu plugin ‘java‘ 然后就一下子出现了一个完整的java项目结构(后面仔细介绍build.gradle),摸索思考了下,人类历史最伟大的进步便是学会使用工具,而我们手上正有IDE这伟大的工具,而IDE正正让我跳过了官方文档的第一个坑。我们团队应该大多都是使用IDEA进行开发的,因此我下面的Demo都是利用idea的。
 
1.使用IDEA,new project,此时惊奇的发现IDEA集成了Gradle
 技术分享

 

 

2.填写好点击下一步

 技术分享

3.此时应该发现Gradle的建立和Maven相差无几,把上面的两项勾上,让IDE去做它该做的事情,点击下一步。

技术分享

4.继续点击下一步。

 

 

 技术分享

 

 

5.此时我们发现一个熟悉的java项目结构出现了

 

技术分享

 

 

6.点击打开build.gradle,下面大致说明一下此文件的意义

技术分享

 

 

在Gradle中,有两个基本概念:项目和任务。请看以下详解:
项目是指我们的构建产物(比如Jar包)或实施产物(将应用程序部署到生产环境)。一个项目包含一个或多个任务。
任务是指不可分的最小工作单元,执行构建工作(比如编译项目或执行测试)。

build.gradle是gradle项目的构建脚本,里面指定了项目与任务。紧接着仔细说一下IDEA构建出项目后build.gradle默认的语句含义。

group ‘JryLearnGradle‘,version ‘1.0-SNAPSHOT‘ :
build名,版本号。

apply plugin: ‘java‘ :
Gradle与Maven一样,特性都是由plugin提供的,Gradle为我们提供了许多有用的插件,apply plugin :‘java‘ ,则是把gradle为java开发写的插件源码引用到build.gradle中(gradle中的plugin都是用groovy写好的代码)

repositories {
mavenCentral()
} :
Gradle仓库可以使用maven或ivy的仓库,我们团队基本使用maven,而IDEA默认使用了Central Maven 2的仓库,而加入maven仓库,gradle提供了三种选择给我们使用,分别是:
mavenCentral()别名,表示依赖是从Central Maven 2 仓库中获取的。
jcenter()别名,表示依赖是从Bintary’s JCenter Maven 仓库中获取的。
mavenLocal()别名,表示依赖是从本地的Maven仓库中获取的。
我们可以更改代码 mavenCentral() 选择不用的方式,当然gradle还提供了另外一种方式让我们构建依赖仓库来源,那便是url的方式,下面是使用url方式的方法:
repositories {
     maven {
http://maven.aliyun.com/nexus/content/groups/public        url ""
     }
}

dependencies {
compile group: ‘foo‘, name: ‘foo‘, version: ‘0.1‘
testCompile group: ‘junit‘, name: ‘junit‘, version: ‘4.11‘
} :
这处申明外部依赖,这些依赖存放在外部仓库中。一个外部依赖可以由以下属性指定:
group属性指定依赖的分组(在Maven中,就是groupId)。
name属性指定依赖的名称(在Maven中,就是artifactId)。
version属性指定外部依赖的版本(在Maven中,就是version)。

testCompile是test需要的外部依赖,而compile则是项目运行需要的依赖声明,依赖的声明可以使用快捷方式:
dependencies {
compile ‘foo:foo:0.1‘
testCompile ‘junit:junit:4.11‘
}

默认的build.gradle文件也就解释完了,后面再一点点补充,现在回到我们跑demo的目的,我们是为了建立一个多项目的Spring boot,因此我们需要为SpringBootInGradle添加module,操作和maven差不多。

额外打开一下setting.gradle文件,发现里面就一句 rootProject.name = ‘SpringBootInGradle‘ ,就是project,没啥其他东西,先不管,往后操作。

 

7.右键项目名,new module

 

技术分享

 

8.分别建立JryCoreJryBasicServermodule,点击next

技术分享

 

9.此时我们的项目结构如下图

 

技术分享

 

此时发现IDE实在太好用了,什么都自动为我们做好了,但作为一个学习者,还是得知道IDE在这期间究竟为我们做了什么,先来看看module中的build.gradle吧
group ‘JryLearnGradle‘
version ‘1.0-SNAPSHOT‘
 
apply plugin: ‘java‘
 
sourceCompatibility = 1.5
 
repositories {
mavenCentral()
}
 
dependencies {
testCompile group: ‘junit‘, name: ‘junit‘, version: ‘4.11‘
}
和一开始的没什么区别,其他几个builg.gradle也是如此,再来看看被我们一直忽略的settings.gradle,此时发现settings.gradle多了两行代码:
rootProject.name = ‘SpringBootInGradle‘
include ‘JryCore‘
include ‘JryBasicServer‘
而include的两个module正是我们刚刚添加的,由此推倒,我们需要为一个project增加module只需要在project中的setting.gradle写入include ‘xxxx’ 。
此时再去看看官方文档的做法(https://docs.gradle.org/current/userguide/build_lifecycle.html):
 
 技术分享

 

 

   很简练,就是和我们推倒的一样,接着干。

 

      此时发现,project中有三个build.gradle,里面的东西都一模一样,重复,如论从哪点考虑,我们作为一个多projectproject,应该有module通用的依赖。接下来我们要做的是做到moduleparent中的build.gradle配置。

 

9.module中重复的配置转移到根项目的构建脚本,build.gradle修改添加代码,如下图:

 技术分享

此时发现两段内容代码都是一样的,还是重复,再修改,如下图:

技术分享

 

 

第一个方式是针对某个project的操作,第二个是对根项目下的子项目的通用配置方式

 

如果是多项目构建中的所有项目共享,可以在根项目中的build.gradle加入allproject{}

 

10.JryBasicServer中建立一个类HelloWorld,类中定义方法getString()

技术分享

 

11.修改根项目build.gradle文件,如下图

 

技术分享

build.gradle中除compile project(‘:JryBasicServer‘),其他都是前面解释过的语句,而compile projec的意思便是在JryCore中引入JryBasicServer项目,在打包时,gradle会先把JryBasicServer加载完后再到JryCore。
 
build.gradle修完完后,点击refresh all gradle projects,gradle将下载依赖,此时应该发现gradle从https://repo1.maven.org/maven2中拉取依赖,这肯定不是我们想要的,国内墙太厚,gradle能不能像maven一样,引用阿里的私库呢?
能。
(1)我们先新建一个init.gradle文件,里面内容为:
 
allprojects{
repositories {
def REPOSITORY_URL = ‘http://maven.aliyun.com/nexus/content/groups/public‘
all { ArtifactRepository repo ->
def url = repo.url.toString()
if ((repo instanceof MavenArtifactRepository) && (url.startsWith(‘https://repo1.maven.org/maven2‘) || url.startsWith(‘https://jcenter.bintray.com‘))) {
project.logger.lifecycle ‘Repository ${repo.url} replaced by $REPOSITORY_URL .‘
remove repo
}
}
maven {
url REPOSITORY_URL
}
}
}
 
(2)把init.gradle文件放置在C:\\Users\\USER_NAME\\.gradle中,此时gradle下载依赖时将会先执行init.gradle文件,此时发现下载依赖速度总算正常。
 
这里提一下init.gradle的作用和加载顺序
 
先来简单介绍一下init.gradle这个文件的作用。
  • 它可以用来建立公司内部的配置,如定义公司内部的仓库地址。
  • 它可以用来配置一些全局属性,比如配置持续集成服务器的地址等配置。
  • 它可以用来提供构建所需要的用户的个人信息,如仓库或数据库的用户名和密码。
  • 它可以用来定义开发者机器的环境,比如定义jdk安装在什么位置,android sdk安装在什么位置等等。
  • 最重要的功能之一,它可以用来注册一些监听器。比如监听Gradle事件的发生,做一些额外的操作,例如需要对某个项目构建前和构建后做一些操作,又例如对项目的依赖做检测,检测是否含有snapshot包,在release构建中一般来说是禁止依赖snapshot包的,所以这时候就可以扔出一个异常。
  • 重定向日志。我们可以将gradle默认的日志进行重定向,甚至我们可以不输出默认日志,自定义如何输出gradle产生的日志信息。
 
init.gradle的加载顺序:
1.加载USER_HOME/.gradle/init.gradle文件
2.加载USER_HOME/.gradle/init.d/目录下的以.gradle结尾的文件
3.加载GRADLE_HOME/init.d/目录下的以.gradle结尾的文件
 
11.依赖齐全后,在JryCode新建类PrintHelloController,内容如下
技术分享

 

12.接下来就是run啦,成功跑起后,访问localhost:8080
 
技术分享

 

 

 此时一个多projectSpringBootHelloWorld就完成了,需要打包只需点击Gradle projectsbuild

技术分享

成功build后,我们可以发现在libs中有我们需要的jar包了。

 

一个简单的demo就跑完了,以上都是走马观花式的操作,下面来分析一下Gradle的原理与总结吧。

 

 

深入理解Gradle背后的内容

 

 

 

在理解Gradle内容前,我们需要先理解一下何谓DSL。

 

DSL,领域特定语言,其基本思想是“求专不求全”,不像通用目的语言那样目标范围涵盖一切软件问题,而是专门针对某一特定问题的计算机语言。而Martin Fowler将DSL分为两类:外部DSL和内部DSL。外部DSL是一种独立的可解析的语言,举一个最常见的是例子,SQL,它专注于数据库的操作。内部DSL是通用语言所暴露的用来执行特定任务的API,它利用语言本身的特性,将API以特殊的形式(或者格式)暴露出来的。

 

总结一下,外部DSL是一种特定的独立语言,内部DSL是通用语言为实现特殊目的提供的API。

 

 

 

Gradle开发团队为了使用Gradle更好的构建描述,为Gradle提供了一套内部DSL,语言正是基于上文提及到的Groovy,理解了内部DSL,就能知道我们在跑demo时用到的各种dependenices{},project{},等等语句,底层其实就是调用用groovy代码封装好的api方法,继而也能理解Gradle中的plugin其实也就是用groovy写好的代码块,apply一个plugin,其实也相当于我们的开发的import。

 

 

 

了解了Gradle底层的实现,就应该来学习Gradle的设计思想。

 

Gradle是按照DDD(领域驱动设计)的思想设计和开发的,其三个领域对象:Project、Task、Action。而官方文档是这么说的,一个构建是由多个project组成,一个project是由多个task组成,task之间的依赖关系,构成了整个构建的流水线。下面仔细说一下三个领域对象的意义。

 

Project: Project是Gradle最重要的一个领域对象,我们写的build.gradle脚本的全部作用,其实就是配置一个Project实例。

 

Task:Gradle的Task等同于Ant的Target。 我们跑demo时在build.gradle写的dependenices{},project{},等等就是一个个的task,task是闭包的。

 

Action:Task可以包含n个Action,Task提供了doFirst和doLast方法来给自己添加Action,如下面的例子一样。

 

.task myTask {  

 

   doFirst {  

 

       println ‘hello‘  

 

     }  

 

    doLast {  

 

        println ‘world‘  

 

     }  

 

 }  

 

 

 

稍微总结一下上文,通过我们跑的demo,结合刚刚介绍,Gradle没有一开始的神秘,我们其实可以把它理解为api,它的配置文件其实就是我们一直编写的代码,我们要使用某功能的时候,按往常一样,去看一下官方API就行了

 

 

 

明白了Gradle底层设计和设计思想,接下来补充一下Gradle运行的生命周期。

 

Gradle的生命周期

 

1. Initialization -初始化阶段,初始化阶段会执行项目根目录下的settings.gradle文件,来分析哪些项目参与构建。

 

2. Configuration -配置阶段,配置阶段会去加载所有参与构建的项目的build.gradle文件,会将每个build.gradle文件实例化为一个Gradle的project对象。然后分析project之间的依赖关系,下载依赖文件,分析project下的task之间的依赖关系。

 

3. Execution -执行阶段,执行阶段来执行具体的task。

 

 

 

 

 

总结Gradle

 

Gradle对比Maven,最直观的便是,Maven的POM用XML写,内容标准,以致有所古板,而Gradle的配置文件则使用groovy编写,用代码编写的Gradle更加灵活,同时也更加简洁,而其提供的plugin也为其提供强大的功能。

 

Gradle对比Ant,Ant同样使用XML,XML文件臃肿庞大,Gradle的DSL就显得更加灵活。

 

前面两面两点都是说Gradle的优势,约定人性化,灵活性更高,但这里有必要提一下,就效率而言,Gradle与Maven和Ant并相差无几。毕竟没有完美的东西。

 

 

 

 

 

以上都是我个人在学习Gradle的笔记,内容不全,不能顾全全部,gradle还有很多很多没接触到的地方没提及到,后面再有心得,一点一点补充。

 

 

 
































以上是关于Gradle入门笔记的主要内容,如果未能解决你的问题,请参考以下文章

springmvc学习笔记-入门程序小结

JWT入门 笔记

webpack入门笔记

集成电路模拟版图入门-版图基础学习笔记

集成电路模拟版图入门-版图基础学习笔记

Python入门笔记