读书笔记《gradle-essentials》与Gradle合作的真实世界项目
Ant 是最初和最流行的构建工具之一,与其他基于脚本的原生构建工具相比,它使构建和部署过程更加简单。不过,您仍然可以找到许多使用 Ant 构建脚本来构建项目的项目。 Ant 是根据命令式编程模型的哲学开发的,它告诉系统要做什么以及如何去做。因此,您可以控制构建脚本的每一个动作或步骤。以下是构建任何 Java 项目的样例 Ant 构建脚本。在这里,我们只考虑构建 Java 项目所需的最少任务,因为我们的目的是讨论从 Ant 脚本迁移到 Gradle 脚本的策略:
在这里,我们定义了clean
、compile<三个target /code> 和
createJar
,它将删除目录,创建目录,编译源目录中的 Java 文件,最后创建 .jar
文件,分别。为了将构建脚本从 Ant 迁移到 Gradle,开发人员可以遵循三种不同的策略,如下所示:
导入 Ant 文件
使用 AntBuilder API
将 Ant 任务重写为 Gradle 任务
我们将通过一个例子来讨论它们中的每一个。
第一种也是最简单的迁移方法是将 Ant 脚本文件直接导入 Gradle 脚本。考虑以下结构:
这里项目名称为Chapter6
,Java源码目录为src/main/java
,Ant构建脚本文件为build.xml
。 build.xml
的源代码在上面提到过。现在,作为迁移的一部分,使用以下内容创建 build_import.gradle
文件:
就这些。是的,我们已经成功地将 Ant 构建脚本迁移到 Gradle 脚本。现在,尝试执行以下命令:
执行这个后,可以找到build
/classes
和
dist
目录,dist
包含JavaProject.jar< /代码>文件。
另一种迁移方法是使用AntBuilder API。默认情况下,Gradle 向用户提供了一个 AntBuilder 对象 ant
。用户可以直接在 Gradle 脚本中使用该对象来调用 Ant 任务。以下是使用 AntBuilder API 的 build_antbuilder.gradle
文件的示例代码:
在这里,您可以看到我们使用了不同的 Ant 任务,例如 mkdir
、javac
、jar
等等,作为 ant
对象的方法。现在,执行以下命令:
同样在这里,您 会发现相同的输出,也就是说,它将创建 build
/
classes 目录中找到类文件,在
dist
目录中您可以找到
。 jar
文件。
这 是最后的方法。使用这种方法而不是使用 ant
对象,您实际上是使用实际的 Gradle 任务重写了完整的构建逻辑或功能。遵循这种策略的一个简单方法是,用户首先需要在逻辑上理解用 Ant 编写的完整流文件,然后将其逐步转换为 Gradle 脚本。对于 Ant 中定义的所有目标,用户可以在 Gradle 中创建任务,对于 Ant 中定义的所有任务,用户可以使用 Gradle 特性来复制相同的行为。 Gradle 提供了不同的标准插件来支持构建需求的大部分步骤。插件有自己的生命周期,在插件的帮助下,用户可以避免为通用构建功能重写大量样板脚本。 java
插件就是一个这样的插件。我们已经在Chapter 2中看到了java
插件细节,构建 Java 项目。如果我们想将此 Ant 脚本迁移到 Gradle 脚本以构建 Java 项目,用户只需使用 Java
插件即可完成工作。
考虑具有以下内容的 build.gradle
文件:
如果开发人员遵循 java
插件的默认约定,他只需要编写这一行来构建 Java 项目,并在执行 gradle build
命令,所有必需的步骤都将完成,例如编译代码、执行单元测试用例和准备 .jar
文件。但是,情况并非总是如此。许多遗留项目不遵循约定,它们可能有自己的约定。 gradle
插件提供了根据项目需要配置插件的灵活性。我们将在下面的示例代码中将 Ant 脚本重写为 Gradle 脚本:
前面的代码片段展示了如何将 Ant 脚本重写为 Gradle 脚本。在执行 gradle createJar
命令时,它会生成与上述迁移策略相同的输出。
Maven,另一个构建工具中的,在Ant之后最流行,它还附带了依赖管理解决方案,解决了用户在Ant中面临的问题. Ant 的第一个问题是命令式编程,用户必须编写大量样板代码。另一个问题是依赖管理。 Ant 没有任何内置的依赖管理解决方案(Ant 后来与 Ivy 集成用于依赖管理)。用户必须在需要下载的构建文件中写入每个 JAR 文件路径,并且在传递依赖的情况下,用户识别每个依赖 JAR 并在构建中提及 JAR 名称太复杂了文件。此外,在版本冲突的情况下,它会消耗开发人员的大量精力。 Maven 带有声明式编程模型和内置的依赖管理解决方案。 Gradle 也是建立在这些原则之上的;因此,从 Maven 迁移到 Gradle 对用户来说似乎很舒服。
与 Ant 迁移一样,Gradle 不提供任何导入功能或内置 Maven 对象。用户需要将 Maven 脚本重写为 Gradle 脚本。以下是一些有助于您顺利从 Maven 迁移到 Gradle 的概念:
插件声明
共同约定
依赖管理
存储库配置
让我们继续解释这些概念:
插件声明:插件 是 Maven 和 Gradle 的关键驱动程序功能。与 Maven 插件一样,Gradle 也将其大部分功能打包到插件中。在 Maven 中,用户包含以下 XML 格式的插件:
要包含插件,用户只需要编写
apply plugin
语句,如下所示:通用约定:在 Maven 和 Gradle 中,总是附带一个插件其功能的一些常见约定。例如,如果用户包含
java
插件,通常的约定是源代码位置应该是src/main/java
,测试代码位置应该是src/test/java
,以此类推。如果用户包含插件并遵循相同的约定,那么他可以避免编写任何可以节省时间和精力的样板代码。依赖管理:Maven 和 Gradle 都内置了依赖管理特征。用户不需要关心项目所需的每个单独的 JAR。他只需要提到项目中的一级依赖,其余的都由构建工具来处理。
在 Maven 中,用户可以按以下格式提及依赖项:
要在 Gradle 中定义依赖项,用户必须使用以下语法:
什么范围是Maven,依赖配置是Gradle。您可能已经观察到 Maven 中的 scope 属性和 Gradle 中的依赖 配置属性。在 Maven 中,范围标识需要下载构建依赖项的哪个阶段。在 Gradle 中,依赖配置满足了同样的需求。
Repositories 配置:每当我们谈到依赖时,首先出现的就是想到的是存储库。这是您下载依赖项的位置。以下是可以帮助您在 Maven 中提及存储库位置的代码片段:
在 Gradle 中,您可以使用以下语法提及存储库:
正如我们所见,Maven 和 Gradle 在构建任何项目时都遵循相同的理念。主要区别在于 Maven 使用擅长结构的 XML,但在配置构建脚本时可能会很痛苦,而 Gradle 使用作为 DSL 的 Groovy 脚本,在管理和更改默认行为时提供了极大的灵活性。
构建软件没有多大意义,除非您将软件发布到一些公共存储库,以便在需要时可以被其他软件或项目重用。我们在下载依赖项时讨论了存储库。存储库的另一个方面是将构建结果(JAR、WAR、EAR 等)上传到某个公共位置,以便其他开发人员可以下载它。 Gradle 中的不同插件提供了一种自动化方式来发布插件的默认工件。例如,java
插件提供上传 JAR 文件的任务,war
插件提供上传 WAR 文件的任务, scala
插件提供上传 JAR 文件的任务,等等。用户只需要配置 上传存储库 位置。如果用户不想上传默认构建工件或用户想要上传一些自定义工件,他可以轻松自定义 Gradle 任务以上传其他工件以及根据他的自定义要求。
正如我们看到的,一个java
插件提供了不同的配置,比如compile、testCompile、runtime等等on,下载特定范围的 JAR。为了上传工件,Gradle 提供了一种额外的配置, archives。用户可以在档案配置中配置工件,并使用 uploadArchive
任务,他可以将工件上传到存储库。
以下是构建文件(build_uploadArtifact.gradle
)的示例示例,用于上传由 java
插件生成的 JAR 文件:
您可以执行 gradle –b build_uploadArtifact.gradle uploadArchives
命令上传工件。作为生命周期的一部分,它将构建和上传工件。
在前面的示例中,uploadArchives
任务将工件上传到存储库(在 URL 中提到)。如果它是安全存储库,您可以提供用户名和密码,或者忽略它。您注意到我们在这里没有提到档案,那么 会被上传吗?正如我们已经讨论过的,java
插件构建 JAR 文件,war
插件构建 WAR 文件,等等。因此,插件生成的默认工件将默认作为 uploadArchives
任务的一部分上传。我们将看到另一个关于如何上传您的自定义工件的示例。
以下是 build_uploadCustom.gradle
文件:
现在,执行 gradle –b build_uploadCustom.gradle uploadArchives
命令:
在这里,您可以发现执行构建脚本后,创建了一个新目录tempRepo
。这包含由 Gradle 脚本发布的所有上述工件(ZIP、JAR 和 XML 文件)。
在前面的示例中,我们介绍了以下两种情况:
上传自定义文件(XML 和 ZIP 文件以及默认工件)
上传到本地文件系统(不在中央存储库上)
如果您将任何其他自定义文件(JAR、WAR 或任何其他文件)配置到档案,它也会被上传到存储库。在这里,我们配置了两个附加文件,一个 .xml
文件和一个 .zip
文件以及默认的 Java 工件。如果您想与您的团队成员共享您的工件,同时又不想将工件上传到存储库,除非它通过集成测试,Gradle 让您可以使用 flatDir
。
Gradle 最近引入了一个 maven-publish
插件来更好地控制发布过程。它为您提供了许多额外的灵活性以及默认的发布任务。用户可以修改 POM 文件、发布多个模块等等。
持续集成(CI)是你可以随处阅读的最流行的流行语之一。顾名思义,CI就是每次集成代码库的过程;每当有人对存储库进行提交时。它编译代码,运行单元测试用例并准备构建。用户在这里获得的好处之一是,如果存在编译问题和集成问题,用户可以在早期阶段弄清楚,而不是为时已晚。以下是 CI 工具遵循的通用工作流程:
Gradle 如何适应这个流程?要为任何软件规划构建和部署自动化解决方案,我们需要一组不同的工具来协同工作以实现共同目标。 Jenkins 是有助于集成完整工作流程的集成工具之一。它也适用于插件的概念;您可以根据需要向 Jenkins 添加不同的插件(例如 Gradle、Git、Svn 等),并对其进行配置以规划自动化流程。
在这里,我们假设您已经安装了 Jenkins。您可以通过导航到 Manage Jenkins | 来安装 Gradle 插件 | 管理插件 | 搜索 Gradle。
安装插件后,您可以使用以下屏幕截图在 Jenkins 中配置作业:
在项目配置界面下,您需要配置存储库路径。默认情况下,Jenkins 提供 CVS 和 SVN 插件。如果您需要任何其他存储库(perforce 或 Git),您可以添加相应的插件。仓库配置完成后,需要配置Build Triggers。它允许您定期触发构建,或者,如果您想在每次提交时构建,您可以选择 Poll SCM。现在,是时候配置将构建项目的构建脚本了。
在 Build 菜单下,您可以选择 Invoke Gradle script:
如果你是使用默认构建文件名build.gradle
,则无需配置构建文件。在 Task 下,您可以提及要执行的任务的名称。例如,如果要构建项目,可以在文本框中提及 build
。
配置完成后,您可以点击左侧菜单中的Build Now来构建项目。完成后,单击相应的内部版本号,它将在主屏幕上显示 Console Output:
文档是开发生命周期的重要组成部分之一,没有得到开发者的足够重视。如果代码没有正确记录,它总是会增加维护工作,如果代码缺少文档,新团队成员也需要时间来理解代码。当您将 Java 插件 应用到构建文件时,Gradle 会为您提供一个 javadoc
任务。默认情况下,Gradle 会为您的代码生成初始文档,即使用户没有在文件中提及任何 Javadoc。
考虑以下 Java 示例代码:
现在,尝试执行以下命令:
此命令 将在 <project> 处生成基本的 Java 文档。 \build\docs\javadoc
。
根据要求,您可以在上面添加自己的标签(@description
、@param
等)和详细信息类并获取更新的 Java 文档。
在本章中,我们讨论了从现有构建工具到 Gradle 的不同迁移策略,这对于计划将现有 Ant 和 Maven 脚本迁移到 Gradle 的用户来说非常方便。我们还讨论了如何将工件发布到存储库,这是任何构建工具的关键功能,它可以帮助用户始终从存储库中获取最新的工件。我们在 Jenkins 的帮助下讨论了 CI 框架,以及 Gradle 如何适应这个流程,同时自动化构建和部署解决方案。最后,我们讨论了如何为 Java 代码生成文档。
在下一章中,我们将讨论如何将 TestNG 与 Gradle 集成,这将帮助用户将测试用例作为 Gradle 构建的一部分运行。我们还将讨论集成测试策略以及 Gradle 与代码分析和代码覆盖工具的集成。