Gradle:Project,Tasks and Plugins
让我们回忆上一节,在此基础上增加点东西。
总的来说,build.gradle文件是用来驱动Gradle构建过程的,它包含了指令指导如何构建。如果没有这些构建工具我们也会做这些任务,比如编译,测试,构建jar,部署等。
我们不必像上一节那样手写任务,我们的IDES,插件会帮我们解决。有许多插件会帮我们自动调用任务,如果我们遵守一定的语法,剩下的就由gradle帮我们解决。
插件(Plugin)是什么?插件是一种拓展Gradle的机制。Gradle需要知道如何去构建任务。当我们已知构建的过程,可以以此创建预构建的任务。这就是插件的角色。
我们不去关注如何写插件,我们学习使用已有的插件帮助我们完成任务。这些插件增加了一些任务供我们直接使用。
Java plugin
我们从对java开发者最重要的java插件开始。不出所料,该插件增加了如下的能力。
1.编译
2.测试
3.打包
这些包含了我们能对java工程所做的一切。打包一般情况下指jar文件。
任何我们需要使用的插件都需要在build.gradle文件中添加如下语句
apply plugin: <plugin-name>
我们这里,由于我们要使用java插件,我们将使用如下的语句:
apply plugin: "java"
让我们从理解这背后发生了什么开始。
创建文件夹example2。你能使用任意文件夹。只要保证gradle在任何文件夹都可以访问。
在我们的文件夹中创建build.gradle文件,添加下面这行:
apply plugin: "java"
正如前面提到的,插件会增加大量的任务来处理Java工程。让我们执行如下命令来理解都增加了哪些任务:
gradle tasks
将会有如下输出:
Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend
on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles classes 'main'.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles classes 'test'.
如你看到的,已经增加了许多任务,大部分也很好理解:
1.clean会删除构建目录,所有的classes将会被移除以便重新编译。
2.assemble将会创建jar文件。
这些任务会相互依赖,具体看参考文档dependency grgh。
Basic Java Project with Gradle Java plugin
有了这些信息,那么问题来了,我们如何调用这些任务呢?
我们已经知道如何调用任务,我们需要如下命令gradle <task-name>。具体到我们的java工程该如何做呢?
我们将遵循一定的规则,这就意味着java插件将会到指定的文件夹中寻找文件。你可以自定义规则,但这不在我们讨论的范围之内。
从官方文档中,java插件遵循如下的文件结构:
这不是强制的,如果你想有不同的文件结构,查看官方文档的source sets。
什么是source sets?它组织了需要编译和构建的源文件。Java插件定义了2个标准的source set,main和test。main集合包含了源文件,这些文件将被编译成jar文件。test集合包含单元测试代码,使用JUnit或TestNG来执行。
我们将按照默认的文件结构来访者我的源文件和测试文件,这意味着:
1.java文件放在src/main/java文件夹下
2.测试文件放在src/main/test文件夹下
我创建了包名com.mindstorm.quoteapp在src/main/java文件夹中,文件结构如下:
在quoteapp文件夹中有一个名叫Quote.java文件:
package com.mindstorm.quoteapp;
public class Quote {
private Long id;
private String who;
private String what;
public void setId(Long id) {
this.id = id;
}
public void setWho(String who) {
this.who = who;
}
public void setWhat(String what) {
this.what = what;
}
public Long getId() {
return id;
}
public String getWho() {
return who;
}
public String getWhat() {
return what;
}
}
在我们的根目录下example2中有build.gradle文件,该文件只有一条语句apply plugin: “java”
现在,执行如下命令:
gradle assemble
这条命令将你的java文件编译,构建成jar文件。多个其他任务会被执行,
输出如下:
E:\gradle-projects\example2>gradle assemble
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
这条命令的结果是什么呢?如果一切正常,将会有build文件在你的根目录。在该文件夹下的libs文件夹中有example2.jar。
如果你希望清理构建目录,调用gradle clean命令,然后gradle assemble命令。
下面这条命令将会执行check,assemble任务:
gradle -q build
我们稍加改进。如果我们希望生成的jar文件有不同的名字,更新build.gradle文件:
apply plugin: 'java'
archivesBaseName = "quote"
version = '1.0-FINAL'
现在执行gradle assemble,Jar文件将按如下规则命名<name>-<version>.jar,这里是quote-1.0-FINAL.jar。
更多细节参考官方文档: official page of the Java plugin.
The beginning of Dependencies
你的Java工程很少不依赖第三方库,考虑上面的Quote.java文件,如果我们增加toString()方法,使用到了第三方库:Apache Commons JAR.
我们看下代码:
package com.mindstorm.quoteapp;
import org.apache.commons.lang3.builder.ToStringBuilder;
public class Quote {
private Long id;
private String who;
private String what;
public void setId(Long id) {
this.id = id;
}
public void setWho(String who) {
this.who = who;
}
public void setWhat(String what) {
this.what = what;
}
public Long getId() {
return id;
}
public String getWho() {
return who;
}
public String getWhat() {
return what;
}
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
如果你执行gradle assemble命令,将会遇到问题。你将会看到编译错误。
解决方法是修改build.gradle文件,以便它知道如下两件事:
1.编译过程中需要使用到什么Jar文件。
2.到哪里去找这些jar文件。
Gradle的Repository是保存jar文件的地方。Gradle支持主流的Repository比如Maven, lvy等。如果你了解Maven,这听起来很熟悉。
为了配置远程库,在build.gradle中添加如下语句:
repositories {
mavenCentral()
}
这会使Gradle在指定的Maven中心库需找依赖(JAR 文件)。
每个发布在Maven或其他中心库的文件都有如下的特征:
1.group id
2.artifact id
3.version id
比如,你想定位Apache Commons3,3.2JAR,它将会以如下方式呈现:
上面的图片来自Maven中心库,如果你对你的依赖有疑问,在Maven中心库搜索。
Configurations provided by Java plugin
到现在我们为止,我们知道了我们需要在build.gradle文件中提供额外的信息,通过这些信息可以定位到编译时需要的Jar文件。我们明确了去哪里寻找,但是还没有具体指定哪个文件,在我们这里是Apache Commons Lang library。
Gradle引入了Configurations,Configuration是一个依赖的集合,你能利用它们为你的工程声明额外的依赖。
Configuration有哪些?它们叫什么?插件会添加一系列Configurations,我们可以使用它们指定我们的依赖。对于Java 插件有如下标准配置,其中一部分如下:
1.compile
2.runtime
2.testCompile
3.testRuntime
这里我将会引用官方文档:
compile
编译源文件是需要的依赖。
runtime
运行时需要的依赖
testCompile
编译测试源文件是需要的依赖
testRuntime
运行测试时需要的依赖
现在,我们在编译Quote类时,需要依赖Apache Commons Lang 3.3.2,我们在build.gradle中添加如下条目:
apply plugin: 'java'
archivesBaseName = "quote"
version = '1.0-FINAL'
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.3.2'
}
有些注意的地方:
1.每个依赖独自定义
2.你首先指定配置名compile,然后指定库的group, name, version。
3.当前只有一条编译时依赖,你能添加更多其他依赖。
4.还有一个简便的声明依赖的方法:使用'group-value:name-value:version-value',上面的例子里也可以这样声明:
dependencies {
compile 'org.apache.commons:commons-lang3:3.3.2'
}
保存build.gradle,尝试运行gradle assemble命令。这一次会自动从Maven中心库下载jar文件,添加到本地缓存完成编译过程。
注意
首次编译时,需要连接网络,到Maven中心库下载指定文件。以后将直接在缓存中获取,所以确保网络连接正常。
Some more dependencies
既然我们知道怎么添加编译时依赖,自然需要弄明白怎么添加测试依赖。现在我们使用JUnit,测试实例保存在src/test/java文件夹中。
更新build.gradle文件:
apply plugin: 'java'
archivesBaseName = "quote"
version = '1.0-FINAL'
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
}
上面的格式非常熟悉,只是在版本号的地方,使用+号做了代替。这暗示Gradle获取最新的依赖文件。
Download
你可以在这里(需要科学上网)下载整个工程。