简介
Java的自动化构建工具比较多,从最开始的ant,到maven以及现在的gradle。他们的灵活性和功能越来越强大。相对前面的工具来说,gradle使用专门的编程groovy来描述项目构建过程中的一些任务。由于有编程语言的灵活性,它的表达能力更加强,结合一些强大的插件支持,我们可以使用少量的代码和配置来达到项目构建的目的。这里针对一些常见的问题做一个总结。
安装
gradle的安装过程相对来说还是比较简单的,一种最简单的方法就是到它的官网下载:https://gradle.org/gradle-download/。将gradle下载到本地之后,解压到某个目录并设置好gradle的bin目录到PATH环境变量就可以了。
为了验证gradle的安装情况,可以打开命令行输入如下命令:
gradle --version
如果一切安装配置正确的将显示如下的结果:
当然,安装gradle需要先安装java。Java的安装过程在这里就不详述了。
常用命令
在前面验证gradle安装过程中我们已经尝试过gradle --version的命令。还有一些比较常见的命令。
帮助命令
当我们输入命令:
gradle --help
将显示如下的内容:
在不知道gradle有哪些命令选项的情况下,我们会通过这个命令来查看。
查看task列表
gradle在某种程度上和ant也比较像,它里面也像ant一样定义了很多task。像ant里面定义的task是xml形式的,它定义不同任务的顺序,依赖关系等。而gradle里的任务的概念和ant里的差不多,只是它更加灵活。这些task可以是一些插件带的也可以是一些自定义的。
查看任务列表的命令如下:
gradle tasks
一般该命令会显示工程里面定义的所有任务,一个典型的示例如下:
项目初始化
不管是ant, maven还是gradle,他们都有一个用来描述项目构建逻辑的文件。gradle里常用的是使用build.gradle文件来描述它们。如果用命令行来初始化一个gradle工程的话,可以使用命令:
gradle init
当我们在命令行里输入上述的命令的话会在当前目录生成一个如下结构的一系列文件:
这样,一个空的gradle工程就生成了。如果我们看这个目录结构的话会发现这里还多了两个可执行的文件,gradlew和gradlew.bat。它们分别对应于linux和windows系统的可执行文件。因为在不同的目标环境中不一定在机器中安装了gradle,那么就可以通过工程里自带的这个可执行文件来执行gradle相关的命令。这样节省了安装工具的时间。当然,如果我们要在原有的工程中生成这些可执行文件可以通过命令
gradle wrapper
来生成。
自定义任务
project方法
gradle的build脚本从实质上来说就是一个groovy脚本,它里面所有的元素都是基于project和task这两个类。而project和task就是groovy里两个定义好的类,它预先包含了一系列的属性和方法。一些常用的属性和方法有apply, repositories,dependencies。比如说,我们需要在一个工程里使用java插件,并且定义依赖库所在的repository以及所依赖的详细的类库。我们可以使用如下脚本:
project.apply plugin: 'java'
project.repositories {
mavenCentral()
}
project.dependencies {
testCompile 'junit:junit:4.11'
}
这里指定了所使用的java plugin,依赖的详细类库信息。实际上,因为project是脚本里默认定义的类,在实际的脚本里可以省略这一部分:
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.11'
}
project属性
project类除了上述的方法,还有一些有用的属性用于具体项目的定制。有的属性是只读的,比如name, path, parent等。也有一些属性是可写的,比如说project.description, project.version。这些属性可以被一些任务所使用到,比如用来设置编译打包项目版本的任务。
比如说我们定义一个如下的gradle脚本:
description = "a sample project"
version = "1.0"
task printProperties {
doLast {
println project.version
println project.description
}
}
运行命令gradle printProperties则会输出
1.0
a sample project
extra properties
除了前面project定义的一些属性,还有一些用户自定义的属性也可以放在脚本里。一种简单的方式就是将一些自定义的属性字段放到一个ext的命名空间里。比如说我们可以将前面的示例修改成如下:
description = "a sample project"
version = "1.0"
ext {
springVersion = "4.3.2.RELEASE"
emailNotification = "noreply@master.org"
}
task printProperties {
doLast {
println project.version
println project.description
println springVersion
println emailNotification
}
}
这个时候再执行命令gradle printProperties则输出如下的结果:
:printProperties
1.0
a sample project
4.3.2.RELEASE
noreply@master.org
依赖配置和声明
在前面的讨论里我们已经看到了在gradle脚本里怎么声明依赖。我们就是需要在dependencies命名空间下添加所有需要依赖的类库信息就可以了。以上面的示例代码为例:
dependencies {
testCompile 'junit:junit:4.11'
}
这里声明了对junit库的依赖,在依赖部分里testCompile定义了依赖的范围为testCompile,也就是在测试编译的时候依赖的内容。后面由冒号分开的三个部分分别表示依赖库的group id, artifact id和版本号。对于依赖的库可以通过search.maven.org 来查找。
除此之外,还有一个值得注意的问题就是依赖范围的定义。在gradle里,对依赖的定义有6种,他们分别是compile, runtime, testCompile, testRuntime, providedCompile和providedRuntime。它们有不同的适用范围。
- compile: 这是java plugin所引入的一个配置项,它表示程序代码里需要引用这个库才能进行编译工作。像我们在编程中通常引入的spring framework, hibernate等。因为这些库在程序里有直接或者间接的引用。所以被定义为compile类型。大多数我们引用的库就是这个范围的。
- runtime: 这也是java plugin引入的一个配置项。它默认的包含compile依赖。它主要表示这些依赖的库只是在运行的时候需要用到,但是在编译的时候并不需要。典型的比如jdbc的驱动程序。我们在应用程序里只是基于标准的jdbc api来开发,但是在程序具体运行的时候需要指定针对某个数据库的具体驱动程序。比如'mysql:mysql-connector:5.1.37'。
- testCompile: 这也是java plugin引入的配置项。它默认会包含有compile的配置范围。它主要表示在测试代码里所涵盖的引用依赖。在程序代码里并不依赖它。一些常用的库比如JUnit, TestNG, Mockito等都适用于这个范围。
- testRuntime: 这也是java plugin引入的配置。它默认包含有testCompile, runtime的依赖范围。主要表示测试的代码在运行的时候需要的依赖。这些依赖一般不直接用于测试代码的编译中。
- providedCompile: 这是war plugin引入的配置。对于war plugin所涵盖的范围,它主要是引用在一些java web的程序中。所以有一些依赖的api,比如servlet api, 一些应用程序服务器提供的api在编译的时候不需要打包到war包里头,但是它们又需要引用它们,因为它们已经在所运行的服务器里包含了。
- providedRuntime: 这也是war plugin引入的配置。它表示一些在编译的时候不需要提供的依赖库,但是在运行的时候需要。它们一般也是已经包含到应用服务器中了。
tasks
在之前的脚本里我们已经见过一些task定义的示例了。比如说有如下的:
task hello {
doLast {
println 'Hello world!'
}
}
要运行这些task,则需要在gradle命令后面跟上这个task的名字。像这个示例里需要运行gradle hello就可以了。
task配置
task定义好之后,它实际上就是一个groovy的方法。那么在这个方法里,也就是定义的gradle脚本里,我们可以配置它的具体参数。比如有一个如下的task:
task('copy', type: Copy) {
from(file('srcDir'))
into(buildDir)
}
这是一个实现文件拷贝的task。我们可以在task的详细定义里添加更多的内容来定制它们。比如说,我们可以将上述的内容修改成:
task myCopy(type: Copy)
myCopy {
from 'resources'
into 'target'
include('**/*.txt', '**/*.xml', '**/*.properties')
}
这样可以在详细的任务执行里设定详细的参数值。
task依赖
这一点和ant里面定义的task很相似,当一个task它的执行需要依赖于另外一个task的时候,我们需要定义它们的依赖关系以防止逻辑错误。在gradle里面定义这个关系很简单,可以在task声明里定义。比如如下的示例:
task compile {
println 'compile the source'
}
task dist(dependsOn: compile) {
println 'prepare a jar dist'
}
对于多个task的依赖来说,我们可以将依赖描述部分放在task声明里或者另外一个单独的地方。比如有如下的脚本:
task compile {
doLast {
println 'compile the source'
}
}
task testCode {
doLast {
println 'test code'
}
}
task dist(dependsOn: [compile, testCode]) {
doLast {
println 'prepare a jar dist'
}
}
这时候如果我们运行task dist,会先执行它依赖的compile和testCode任务。
常见的项目构建插件
gradle作为构建工具来说,更多被拿来相比较的工具就是maven了。和maven类似,为了支持常用项目的构建,它定义了很多常用的插件,这样对一些常用的项目,比如java工程,java web工程等它都有很好的支持。这些事先定义好的插件包含了一系列的任务,这些任务在很多工程里有一定程度的通用,可以极大的提高工作效率。
java plugin
一个常用的插件就是java,要使用这个插件,只需要在构建文件build.gradle里添加如下的代码即可:
apply plugin: 'java'
如果此时我们运行命令gradle tasks,会发现输出结果里多了很多task。
这些task就是java plugin里面自带的,常用一些比如编译代码的任务compileJava, 打包程序的任务assemble, build以及测试程序的任务testClasses。 更详细的任务列表以及关系可以通过gradle tasks --all来查看。由于不同的任务有一定的依赖关系,所以我们会看到像build任务是依赖于assemble, check等任务的。这种现象在gradle里很常见。
假设我们创建一个如下的目录结构:
这里建立了一个普通的java工程目录结构,其中GreetingService.java和Main.java的详细实现如下:
package com.packtpub.ge.hello;
public class GreetingService {
public String greet(String user) {
return "Hello " + user;
}
}
package com.packtpub.ge.hello;
public class Main {
public static void main(String[] args) {
GreetingService service = new GreetingService();
System.out.println(service.greet(args[0]));
}
}
这个时候,如果我们需要编译程序,只需要运行命令
gradle compileJava
运行结束后的程序目录结构如下:
从目录结构中可以发现,编译完之后的代码会被放到一个build的目录下面。而如果需要将编译后的代码打包,则可以执行命令
gradle build
这个时候的程序目录结构如下:
我们可以看到对应的jar包也生成在build目录下了。这个包名和我们创建这个工程的目录名是一样的。如果想要设置生成的jar包名,只需要在build.gradle里添加指定这个包名的内容即可:
archivesBaseName = "my-app"
如果我们再运行前面的命令会发现新生成的包名变了。而实现编译打包等功能来处理这个工程的build脚本非常简单,只有两行:
apply plugin: 'java'
archivesBaseName = "my-app"
在java plugin里还有一个比较重要的task,就是将编译打包后的结果上传到某个地方,比如本地的文件或者repository服务器上。比如说我们像将本地的工程包上传到某个maven服务器,则可以使用如下的配置:
uploadArchives {
repositories {
maven {
credentials {
username "user1"
password "user1"
}
url "http://company.private.repo"
}
}
}
在后续项目的开发中,如果需要引用到这个库就和引用公开的第三方库一样方便了。当然,如果像将工程包放到本地的一个目录上,也可以这样设置:
uploadArchives {
repositories {
flatDir {dirs "./tempRepo"}
}
}
application plugin
在前面java pllugin里,我们发现它定义了很多tasks用来提高项目的编译测试等任务,在某些情况下,如果我们希望直接通过gradle命令来将项目打包运行和发布的话。还有一个经常要用到的插件是application。同样,我们只需要在原来的脚本里添加一行代码将这个插件包含进来就可以了。以前面的示例为基础,假设我们想要运行这个程序,那么可以将build.gradle修改如下:
apply plugin: 'java'
apply plugin: 'application'
mainClassName = "com.packtpub.ge.hello.Main"
run.args = ["Reader"]
repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}
在上述的脚本里,我们不仅仅引入了application plugin,而且还设定了程序运行时的主入口启动类和程序的启动输入参数。所以如果运行命令:
gradle run
我们将看到如下的结果:
:compileJava
:processResources UP-TO-DATE
:classes
:run
Hello Reader
当然,除了上述的启动运行程序的命令,application plugin还提供了一些程序打包的任务支持。如果我们运行命令:
gradle distZip
在项目中会增加一个.zip的打包好的文件。最终的目录结构如下:
application plugin带来的更多任务可以通过gradle tasks来查看。
war plugin
war plugin主要是应用于java web工程里,它和java plugin之间还是一个继承的关系。也就是说,如果我们的应用里引入了war plugin,就没必要再引用java plugin了。
一个简单的java web工程对应的配置如下:
apply plugin: 'war'
repositories {
mavenCentral()
}
dependencies {
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
}
在脚本里面,我们只需要指定插件和依赖的库,然后感觉所有需要的东西就已经具备了。 假设我们工程目录结构如下:
它的详细实现代码见后面附件里的内容。如果我们需要将程序打包的话,只需要执行命令:
gradle war
就会发现在build/lib的目录下有一个打包好的war包了。
关于java web工程来说,还有一个重要的问题就是要运行这些打包的结果。以往我们都是采用手动的过程将打包好的内容拷贝到一个应用服务器的指定目录里,比如tomcat, jetty等。实际上gradle里也有对应的插件来支持,这样就使得我们运行web工程的效率更加高。一个典型的插件就是gretty。
因为gretty不是gradle原生自带的插件,它是一个扩展的插件,我们需要指定它的版本等信息。
plugins {
id "org.akhikhl.gretty" version "1.4.0"
id 'war'
}
gretty {
servletContainer = 'tomcat8'
port = 8080
}
repositories {
mavenCentral()
}
dependencies {
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
}
这里,因为gretty是指定工程运行的插件,它需要提供我们运行的时候是使用的哪个服务器以及运行时的端口。所以需要指定servletContainer和port。像这里指定的是使用tomcat8服务器,启动的端口是8080。如果我们想使用别的服务器,比如jetty9,可以将上述代码里gretty的部分修改成如下的内容:
gretty {
servletContainer = 'jetty9'
port = 9080
}
运行工程应用的命令则比较简单,使用命令:
gradle appRun
程序启动后会显示如下内容:
打开浏览器就能访问我们创建的应用了。
多工程构建
在我们实际的工程应用中,经常会创建多个工程,而且这些工程之间有一定的依赖关系。那么我们经常需要将这些多个工程组织起来。我们可以通过一个对应的配置文件来实现。
比如说我们有一个如下的项目,它由多个工程组成:
在图中显示至少包含有core, web两个工程。那么,我们可以将这个build里面所有需要引用到的工程定义在settings.gradle文件里。比如说:
include 'core',
'core:models', 'core:repository', 'core:services',
'client', 'client:client-api',
'client:cli-client', 'client:desktop-client',
'web', 'web:webapp', 'web:webservices'
这个时候,如果我们运行命令:
gradle projects
我们将看到如下的结果:
这里比较有意思,虽然在项目的结构里我们只看到有两个子工程,但是通过定义好的settings.gradle文件,程序逻辑里包含的工程还是以这个文件为基础的。
这里还有一个比较有意思的地方在前面的依赖定义部分没有提到。就是有时候我们定义的多个工程中间它们某些相互有依赖的关系。那么我们需要在文件里面也给定义出来。在这里它们的使用方式和前面的依赖管理很相似。在settings.gradle文件里定义好总体的包含关系之后。只需要在具体的某个工程里引入就可以了。比如说我们有工程web-app,它依赖于另外一个工程services。那么我们只需要在web-app里面的build.gradle里添加如下内容:
dependencies {
compile project(':services')
}
这样,就解决了项目之间的依赖关系。这和引用一个类库的方式几乎一样。
IDE集成插件
我们使用gradle开发如果和一些集成开发工具结合起来更能够提升项目开发的效率。所以gradle里也提供了对常用开发工具的支持,比如eclipse, IDEA等。如果需要引入它们的话,只需要在工程里引入对应的plugin就可以了。比如说,我们想要让工程支持eclipse和IDEA的导入。我们可以在build.gradle里加入如下部分:
apply plugin: 'eclipse'
apply plugin: 'idea'
如果我们希望在对应的IDE里导入它们,只需要执行命令:
gradle eclipse
或者:
gradle idea
就可以了。这样可以充分利用IDE带来的便利。
总结
gradle是一个比较新的项目编译构建工具,它因为是基于groovy来构造项目构建的逻辑,所以有充分的表达能力和灵活性。这里针对常用项目开发里使用到的一些功能做一个总结。包括有它的安装配置,常用的插件和一些自定义任务的构建。实际上gradle还有很多很灵活的应用值得我们去深入学习思考,而且,它本身使用的编程语言groovy也值得进一步的学习。
参考材料
https://gradle.org/
https://www.amazon.com/Gradle-Essentials-Community-Experience-Distilled/dp/1783982365/ref=sr_1_1?s=books&ie=UTF8&qid=1482032176&sr=1-1&keywords=gradle+essentials
相关推荐
### Gradle 学习知识点概览 #### 一、Gradle 概述 - **定义**:Gradle 是一种基于 JVM 的开源自动化构建工具,它使用 Groovy 或 Kotlin DSL(领域特定语言)来声明构建脚本,支持增量构建以及多项目构建等功能。...
10. 常见问题与解决方案:总结在使用Android Gradle过程中可能遇到的一些常见问题,并提供解决方案,以便快速定位并解决问题。 根据标题和描述,这本书籍是专门为Android开发者编写的,旨在全面系统地教授Gradle在...
总结来说,Gradle是一种目前被广泛采用的构建工具,它的脚本比其他工具更为简洁和灵活,尽管在速度上可能稍逊一筹。对于那些正在寻找更加高效、易于理解构建系统工具的Java开发者,特别是那些已经在使用Maven或Ant的...
总结起来,"gradle-1.0.zip"是Android Studio项目配置Gradle的一个重要资源,它使得我们能够在本地快速启动和配置构建环境。理解Gradle的工作原理和使用方法,对于提升Android开发效率至关重要。随着版本的迭代,...
以下是针对“在Eclipse下利用Gradle构建系统”这一主题的知识点总结: ### Gradle概述 **Gradle** 是一种用于自动化构建流程的工具,相较于传统的构建工具如Ant和Maven,Gradle提供了一种更加灵活、简洁的方式来...
`samples`目录可能包含了一些示例项目,帮助开发者快速上手和学习Gradle的使用。`lib`目录则包含了Gradle运行所需的库文件,这些库支持了Gradle的各种功能。最后,`docs`目录很可能包含Gradle的官方文档,包括API...
总结来说,"Gradle 构建仓库3"是一个学习Gradle构建技巧和实践的资源,通过分析其中的项目和脚本,开发者可以提升对Gradle的理解,掌握更高效的构建流程。无论是对于初学者还是经验丰富的开发者,这都是一个宝贵的...
总结来说,Gradle-4.2-all.zip是Gradle 4.2版本的完整包,包含了构建项目所需的所有组件,特别适合那些希望在离线环境中工作或需要快速搭建构建环境的开发者。通过其强大的依赖管理、插件系统、并行构建等功能,...
Hubert的背景有助于他从实践中总结出有用的技巧和经验,帮助读者更好地理解Gradle的高效用法。 本书由Packt Publishing出版,第一版于2012年10月发布,全书共382页,英语编写,国际标准书号为ISBN-10: *** 和 ISBN-...
《深入理解Gradle 6.0在Android Studio中的应用》 在Android开发中,Gradle是一个不可或缺的构建工具,它的存在极大地...通过不断学习和实践,我们可以更好地利用Gradle来优化我们的项目,让开发工作更加流畅高效。
在本篇文章中,我们将深入探讨有关Gradle下载地址的...通过本文的学习,读者应该能够掌握如何下载并安装Gradle,以及如何利用Gradle进行项目的自动化构建。希望本文能为正在学习或使用Gradle的开发者们提供一定的帮助。
IntelliJ IDEA是一款广受欢迎的Java开发集成环境,它的强大功能和灵活性部分归功于其丰富的插件系统。Gradle是一种先进的构建自动化工具...通过学习和掌握上述配置方法,开发者能够更好地管理和优化他们的Gradle项目。
《Gradle-4.5全解析:Android Studio的构建利器》 在Android开发领域,Gradle作为主流的构建工具,其重要性不言而喻。...在实际工作中,不断学习和探索Gradle的新特性,有助于保持与时俱进,应对日新月异的开发环境。
《Gradle 6.3 全面解析:构建自动化的新高度》 Gradle,作为一款强大的构建自动化工具,已经成为了Java开发领域中的...因此,深入学习和理解Gradle 6.3,对于每一个Java或Android开发者来说,都是一项重要的技能提升。
总结来说,Gradle 4.0.2源码的下载提供了深入学习和定制Gradle构建过程的机会。对于Android开发者,理解Gradle的工作原理和优化技巧,能够提高开发效率,提升项目的构建质量和速度。而离线包的提供,为网络条件不佳...
《Gradle 4.4 全面解析:深入理解与实战指南》 Gradle 是一个强大的构建自动化工具,尤其...而提供的"gradle使用教程.txt"和"gradle-4.4-all.zip"资源将有助于深入学习和实践Gradle 4.4,为你的开发之旅增添强大助力。
总结起来,Gradle 3.1 是一个注重性能和开发者体验的版本,它在构建速度、插件系统、Android Studio集成等多个方面都进行了优化。对于Android开发者,尤其是那些需要离线环境的人来说,这个版本的Gradle是一个可靠的...