Gradle包装器
您构建了一个任务管理 Web 应用程序的原型。 当您将其展示给您的同事 Mike 后,他说他希望联合起来,通过添加更多高级功能将应用程序提升到一个新的水平。 该代码已提交给版本控制系统 (VCS),因此他可以继续检查代码并开始处理它。
Mike 从未使用过构建工具 Gradle,因此他询问您如何在他的计算机上安装运行时以及使用哪个版本。 由于他没有经历最初设置 Gradle 的过程,因此他还担心在 Windows 计算机上设置 Gradle 与在 Mac 上安装 Gradle 之间的潜在差异。 根据使用其他构建工具的经验,Mike 痛苦地意识到,选择错误版本的构建工具发行版或运行时环境可能会对构建结果产生不利影响。 他经常看到构建在他的机器上成功完成,但在另一台机器上却无缘无故地失败。 在花费数小时进行故障排除后,他通常会发现原因是运行时版本不兼容。
Gradle 为这个问题提供了一个非常方便实用的解决方案:Gradle 包装器。 包装器是一项核心功能,使机器能够运行 Gradle 构建脚本,而无需安装运行时。 它还确保构建脚本使用特定版本的 Gradle 运行。 它通过从中心位置自动下载 Gradle 运行时、将其解压到本地文件系统并使用它进行构建来实现这一点。 最终目标是创建独立于操作系统、系统设置或安装的 Gradle 版本的可靠且可重复的构建。
何时使用包装器 使用包装器被认为是最佳实践,并且对于每个 Gradle 项目都应该是强制性的。 由包装器支持的 Gradle 脚本已完全准备好作为自动化发布流程(例如持续集成和交付)的一部分运行。 |
让我们看看如何为 Mike 和任何其他想要加入团队的开发人员设置包装器。
设置包装器
要为您的项目设置包装器,您需要做两件事:创建包装器任务并执行该任务以生成包装器文件(图 3.6)。
要使您的项目能够下载压缩的 Gradle 运行时发行版,请定义 Wrapper 类型的任务并通过属性 gradleVersion 指定要使用的 Gradle 版本:
task wrapper(type: Wrapper) {
gradleVersion = '1.7'
}
不需要为任务 wrapper 命名——任何名称都可以。 然而,wrapper 在整个 Gradle 在线文档中使用,并作为一种有用的约定。 执行任务:
$ gradle wrapper
:wrapper

因此,您将在构建脚本旁边找到以下包装器文件:
.
├── buildxxx.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar // Gradle 包装微库包含下载和解压分发的逻辑
│ └── gradle-wrapper.properties // 包装器元数据,例如下载分发的存储位置和原始 URL
├── gradlew // 用于执行 Gradle 命令的包装器脚本
└── gradlew.bat
请记住,您只需要在项目上运行 gradle wrapper 一次。 从那时起,您可以使用包装器的脚本来执行您的构建。 下载的包装文件应该被签入版本控制。 出于文档原因,将任务保留在项目中会很有帮助。 它将帮助您稍后通过更改 gradleVersion 并重新运行 wrapper 任务来升级包装器版本。 您可以使用前面提到的构建设置插件,而不是手动创建包装器任务并执行它来下载相关文件。 执行命令 gradle wrapper 将使用 Gradle 运行时的当前版本生成包装器文件:
$ gradle wrapper
:wrapper
接下来,您将使用生成的包装器脚本来引导 Gradle 脚本。
使用包装器
作为包装器分发的一部分,提供了命令执行脚本。 对于 *nix 系统,这是 shell 脚本 gradlew; 对于 Windows 操作系统,它是 gradlew.bat。 您将使用这些脚本之一来运行构建,就像使用已安装的 Gradle 运行时一样。 图 3.7 说明了使用包装器脚本执行任务时会发生什么。
让我们回到我们的朋友迈克。 他从 VCS 中检查了应用程序代码。 他将在项目的源代码树中找到包装文件。 当 Mike 在 Windows 机器上开发代码时,他需要运行包装批处理文件来执行任务。 当他启动本地 Jetty 容器来运行应用程序时,会产生以下控制台输出:
> gradlew.bat jettyRun
Downloading http://services.gradle.org/distributions/gradle-1.7-bin.zip // 从远程服务器下载包装器分发
...
Unzipping C:\Documents and Settings\Mike\.gradle\wrapper\dists\gradle-1.7-
➥ bin\35oej0jnbfh6of4dd05531edaj\gradle-1.7-bin.zip to C:\Documents and
➥ Settings\Mike\.gradle\wrapper\dists\gradle-1.7-
➥ bin\35oej0jnbfh6of4dd05531edaj // 将压缩包装文件解压到预定义的本地目录
Set executable permissions for: C:\Documents and
➥ Settings\Mike\.gradle\wrapper\dists\gradle-1.7-
➥ bin\35oej0jnbfh6of4dd05531edaj\gradle-1.7\bin\gradlew.bat // 设置包装批处理文件的执行权限
:compileJava
:processResources UP-TO-DATE
:classes
> Building > :jettyRun > Running at http://localhost:9090/todo

分发 ZIP 文件是从 Gradle 项目托管的中央服务器下载的,存储在 Mike 的本地文件系统中的 $HOME_DIR/.gradle/wrapper/dists 下。 Gradle 包装器还负责解压发行版并设置适当的权限来执行批处理文件。 请注意,下载只需进行一次。 后续构建运行将重用位于 Gradle 主目录中的运行时的解压安装:
> gradlew.bat jettyRun
:compileJava
:processResources UP-TO-DATE
:classes
> Building > :jettyRun > Running at http://localhost:9090/todo
关键要点是什么? 由 Gradle 包装器执行的构建脚本提供与使用本地 Gradle 安装运行时完全相同的任务、功能和行为。 同样,您不必遵守包装器为您提供的默认约定。 其配置选项非常灵活。 我们将在下一节中讨论它们。
定制包装器
有些企业有非常严格的安全策略,特别是如果您在政府机构工作,则禁止访问网络外部的服务器。 在这种情况下,如何使您的项目能够使用 Gradle 包装器? 一切都在配置中。 您将更改默认属性以将托管运行时发行版的企业服务器作为目标。 当您这样做时,您还将更改本地存储目录:
task wrapper(type: Wrapper) {
gradleVersion = '1.2' // 请求Gradle版本
distributionUrl = 'http://myenterprise.com/gradle/dists' // 用于检索 Gradle 包装器分发的目标 URL
distributionPath = 'gradle-dists' // 相对于 Gradle 主目录解压包装器的路径
}
很简单,对吧? 还有更多选择可供探索。 请务必查看 Gradle 包装器 DSL 文档以获取详细信息: http://gradle.org/docs/current/dsl/org.gradle.api.tasks.wrapper.Wrapper.html 。
总结
在第 2 章中,您学习了如何通过向项目添加任务来表达和执行简单的逻辑。 在本章中,我们走得更远。 您实现了一个全栈 Java 应用程序并使用 Gradle 来构建它。 许多 Java 项目本质上都是相似的。 他们需要编译 Java 源代码、运行测试并捆绑包含类的 JAR 文件。 幸运的是,您不必自己编写这些任务即可在项目中实现这一点。 通过使用 Gradle 插件,您只需在构建脚本中编写代码即可。
您首先使用 Gradle 附带的 Java 插件。 将插件应用到您的项目中添加了预配置的任务和由固执己见的框架包装的标准化项目结构。 定制项目要求需要灵活的约定。 我们探索了自定义插件引入的默认约定的选项。 了解您的选择的关键是 Gradle DSL 和 API 文档。
在简短回顾了 Java Web 应用程序开发的基础知识之后,我们讨论了如何通过 Java EE 兼容的 Web 组件来扩展示例项目。 Gradle 通过 War 和 Jetty 插件帮助您简化 Web 开发。 War 插件协助组装 WAR 文件,Jetty 插件提供对轻量级 Servlet 容器的高效部署。 您看到约定优于配置范例也应用于这个动态二人组。 您还了解到,使用包装器是每个 Gradle 项目的最佳实践。 它不仅允许您在未安装 Gradle 的计算机上运行项目,还可以防止版本兼容性问题。
所提供的插件提供的功能比我们讨论的要多得多。 要详细了解其功能,您可以访问在线用户指南 ( http://www.gradle.org/docs/current/userguide/standard_plugins.html )。 本章完成了本书的第 1 部分。 在第 2 部分中,我们深入研究了 Gradle 的许多核心概念。 下一章将重点介绍 Gradle 的构建块、任务的细节以及构建生命周期。