Java 插件
Gradle 是一个通用工具。它可以通过脚本构建任何你想要实现的东西,真正实现开箱即用。但前提是你需要在脚本中编写好代码才行。
大部分 Java 项目基本流程都是相似的:编译源文件,进行单元测试,创建 jar 包。使用 Gradle 做这些工作不必为每个工程都编写代码。Gradle 已经提供了完美的插件来解决这些问题。插件就是 Gradle 的扩展,简而言之就是为你添加一些非常有用的默认配置。
Gradle 自带了很多插件,并且你也可以很容易的编写和分享自己的插件。Java plugin 作为其中之一,为你提供了诸如编译,测试,打包等一些功能。
Java 插件为工程定义了许多默认值,如 Java 源文件位置。如果你遵循这些默认规则,那么你无需在你的脚本文件中书写太多代码。当然,Gradle 也允许你自定义项目中的一些规则,实际上,由于对 Java 工程的构建是基于插件的,那么你也可以完全不用插件自己编写代码来进行构建。
一个基本的 Java 项目 (demo3)
采用 Java 插件
//在 build.gradle 文件中
apply plugin: 'java'
使用 gradle tasks 就可看到 Java 插件添加了哪些任务
- java项目的标准目录如下:
project
+build
+src/main/java
+src/main/resources
+src/test/java
+src/test/resources
Gradle 默认会从 src/main/java 搜寻打包源码,在 src/test/java 下搜寻测试源码。并且 src/main/resources 下的所有文件按都会被打包,所有 src/test/resources 下的文件 都会被添加到类路径用以执行测试。所有文件都输出到 build 下,打包的文件输出到 build/libs 下。
构建 Java 项目
常用的任务
- build 当执行 gradle build 时,Gralde 会编译并执行单元测试,并且将 src/main/* 下面 class 和资源文件打包。
- clean 删除 build 目录以及所有构建完成的文件。
- assemble 编译并打包 jar 文件,但不会执行单元测试。一些其他插件可能会增强这个任务的功能。例如,如果采用了 War 插件,这个任务便会为你的项目打出 War 包。
- check 编译并测试代码。一些其他插件也可能会增强这个任务的功能。例如,如果采用了 Code-quality 插件,这个任务会额外执行 Checkstyle。
外部依赖
通常,一个 Java 项目拥有许多外部依赖。你需要告诉 Gradle 如何找到并引用这些外部文件。
- 添加 Maven 仓库 在 Gradle 中通常 Jar 包都存在于仓库中。仓库可以用来搜寻依赖或发布项目产物。下面是一个采用 Maven 仓库的例子。
// 在 build.gradle 文件中
repositories {
mavenCentral()
}
- 添加依赖 添加依赖。这里声明了编译期所需依赖 commons-collections 和测试期所需依赖 junit。
// 在 build.gradle 文件中
dependencies {
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
}
- 自定义项目
- 自定义 MANIFEST.MF Java 插件为项目添加了众多默认配置。这些默认值通常对于一个普通项目来说已经足够了。但如果觉得不适用修改起来也很简单。 下面的例子,我们为 Java 项目指定了版本号以及所用的 JDK 版本,并且添加一些属性到 mainfest 中。
// 在 build.gradle 文件中
sourceCompatibility = 1.5
version = '1.0'
jar {
manifest {
attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
}
}
- 为 test 添加系统属性
Java 插件添加的都是一些普通任务,如同他们写在 Build 文件中一样。这意味着前面章节展示的机制都可以用来修改这些任务的行为。
例如,可以设置任务的属性,添加任务行为,更改任务依赖,甚至是重写覆盖整个任务。
在下面的例子中,我们将修改 test 任务,这是一个 Test 类型任务。让我们来在它执行时为它添加一些系统属性。
// 在 build.gradle 文件中
test {
systemProperties 'property': 'value'
}
- 发布jar包
// 在 build.gradle 文件中
uploadArchives {
repositories {
flatDir {
dirs 'repos'
}
}
}
执行 gradle uploadArchives 以发布 jar 包。
- Eclipse 插件 文件若要把项目导入 Eclipse 中,你需要添加另外一个插件到你的脚本文件中。
// 在 build.gradle 文件中
apply plugin: 'eclipse'
执行 gradle eclipse 来生成 Eclipse 项目文件。
示例汇总
- Java 示例 - 一个完整构建脚本
// 在 build.gradle 文件中
apply plugin: 'java'
apply plugin: 'eclipse'
sourceCompatibility = 1.5
version = '1.0'
jar {
manifest {
attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
}
}
repositories {
mavenCentral()
}
dependencies {
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
}
test {
systemProperties 'property': 'value'
}
uploadArchives {
repositories {
flatDir {
dirs 'repos'
}
}
}
补充知识
MANIFEST.MF文件
打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息。
Manifest-Version: 1.0
Created-By: Apache Ant 1.5.1
Extension-Name: Struts Framework
Specification-Title: Struts Framework
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.1
Implementation-Title: Struts Framework
Implementation-Vendor: Apache Software Foundation
Implementation-Vendor-Id: org.apache
Implementation-Version: 1.1
Class-Path: commons-beanutils.jar commons-collections.jar commons-dig ester.jar commons-logging.jar commons-validator.jar jakarta-oro.jar struts-legacy.jar
如果我们把MANIFEST中的配置信息进行分类,可以归纳出下面几个大类:
- 一般属性
- Manifest-Version 用来定义manifest文件的版本,例如:Manifest-Version: 1.0
- Created-By 声明该文件的生成者,一般该属性是由jar命令行工具生成的,例如:Created-By: Apache Ant 1.5.1
- Signature-Version 定义jar文件的签名版本
- Class-Path 应用程序或者类装载器使用该值来构建内部的类搜索路径
- 应用程序相关属性
- Main-Class 定义jar文件的入口类,该类必须是一个可执行的类,一旦定义了该属性即可通过 java -jar x.jar来运行该jar文件。
- 小程序(Applet)相关属性
- Extendsion-List 该属性指定了小程序需要的扩展信息列表,列表中的每个名字对应以下的属性
- <extension>-Extension-Name
- 扩展标识属性
- Extension-Name 该属性定义了jar文件的标识,例如Extension-Name: Struts Framework
- 包扩展属性
- Implementation-Title 定义了扩展实现的标题
- Implementation-Version 定义扩展实现的版本
- Implementation-Vendor 定义扩展实现的组织
- Implementation-Vendor-Id 定义扩展实现的组织的标识
- Implementation-URL : 定义该扩展包的下载地址(URL)
- Specification-Title 定义扩展规范的标题
- Specification-Version 定义扩展规范的版本
- Specification-Vendor 声明了维护该规范的组织
- Sealed 定义jar文件是否封存,值可以是true或者false
- 签名属性
- 签名方面的属性我们可以来参照JavaMail所提供的mail.jar中的一段
Name: javax/mail/Address.class Digest-Algorithms: SHA MD5 SHA-Digest: AjR7RqnN//cdYGouxbd06mSVfI4= MD5-Digest: ZnTIQ2aQAtSNIOWXI1pQpw== 这段内容定义类签名的类名、计算摘要的算法名以及对应的摘要内容(使用BASE方法进行编码)
- 自定义属性
除了前面提到的一些属性外,你也可以在MANIFEST.MF中增加自己的属性以及响应的值,例如J2ME程序jar包中就可能包含着如下信息MicroEdition-Configuration: CLDC-1.0 MIDlet-Name: J2ME_MOBBER Midlet Suite MIDlet-Info-URL: http://www.javayou.com MIDlet-Icon: /icon.png MIDlet-Vendor: Midlet Suite Vendor MIDlet-1: mobber,/icon.png,mobber MIDlet-Version: 1.0.0 MicroEdition-Profile: MIDP-1.0 MIDlet-Description: Communicator
关键在于我们怎么来读取这些信息呢?其实很简单,JDK 给我们提供了用于处理这些信息的 API,详细的信息请见 java.util.jar 包中,我们可以通过给 JarFile 传递一个 jar 文件的路径,然后调用 JarFile的getManifest 方法来获取 Manifest 信息。