Gradle 是 Stackify 的综合 Java 开发人员指南中的几个Java 开发工具之一,但它并不是唯一需要考虑的构建自动化工具。Maven 是一种较旧且常用的替代方案,但哪种构建系统最适合您的项目?使用其他工具,例如Spring,允许开发人员在两个系统之间进行选择,再加上两者的集成数量越来越多,决定很大程度上取决于您。
您的项目规模、您的定制需求以及其他一些变量可以帮助您进行选择。让我们来看看。
1
Gradle
Gradle是一个完全开源的构建自动化系统,它使用您在 Apache Maven 和 Apache Ant 上看到的概念。它使用基于编程语言Groovy的领域特定语言,与 Apache Maven 不同,后者使用 XML 进行项目配置。它还使用有向无环图确定任务运行的顺序。
几位开发人员创建了 Gradle,并于 2007 年首次发布,并于 2013 年被 Google 采用为 Android 项目的构建系统。它旨在支持预计会非常庞大的多项目构建。它还允许逐步添加到您的构建中,因为它知道您项目的哪些部分已更新。不再重新执行依赖于更新部件的任务。目前,最新的稳定版本是 3.4 版,于 2017 年 2 月推出。它支持使用 Java、Scala 和 Groovy 进行开发和后续部署,未来还会引入其他项目工作流和语言。
2
Maven
Maven用于使用 Java 进行项目构建自动化。它可以帮助您绘制出特定软件的构建方式及其不同的依赖关系。它使用 XML 文件来描述您正在构建的项目、软件与第三方模块和部件的依赖关系、构建顺序以及所需的插件。打包和编译等任务有预定义的目标。
Maven 将从不同的存储库下载库和插件,然后将它们全部放在本地计算机上的缓存中。虽然主要用于 Java 项目,但您可以将其用于 Scala、Ruby 和 C#,以及许多其他语言。
3
Gradle 与 Maven
两种系统方法的构建方式存在一些根本差异。
Gradle 基于任务依赖关系图——其中任务是完成工作的事物;
Maven 基于阶段的固定和线性模型,在 Maven 中,目标附加到项目阶段,目标与 Gradle 的任务具有类似的功能,即“完成工作的事物”。
性能方面,两者都允许多模块构建并行运行。但是,Gradle 允许增量构建,因为它会检查哪些任务已更新。如果是,则不执行任务,从而缩短构建时间。您可以在 Gradle 上找到的其他显着性能特征包括:
- Java 类的增量编译
- Java 的编译避免
- 将 API 用于增量子任务
- 一个编译器守护进程,它也使编译速度更快
在管理依赖方面,Gradle 和 Maven 都可以处理动态和传递依赖、使用第三方依赖缓存以及读取 POM 元数据格式。您还可以通过中央版本控制定义声明库版本并强制执行中央版本控制。两者都从其工件存储库下载传递依赖项。Maven 有 Maven Central,而 Gradle 有 JCenter,您也可以定义自己的私有公司存储库。如果需要多个依赖项,Maven 可以同时下载它们。
然而,Gradle 在 API 和实现依赖项方面胜出,并且固有地允许并发安全缓存。它还保留存储库元数据以及缓存的依赖项,确保使用相同缓存的两个或多个项目不会相互覆盖,并且它具有基于校验和的缓存,并且可以与存储库同步缓存。此外,Gradle 与 IVY 元数据兼容,允许您定义自定义规则来指定动态依赖的版本,并解决版本冲突。这些在 Maven 上不可用。
您只能在 Gradle 上找到的其他依赖项管理功能包括:
- 兼容库的替换规则的使用
- ReplacedBy 规则的使用
- 更好的元数据分辨率
- 能够用外部依赖项动态替换项目依赖项,反之亦然
Gradle 还让您在处理复合构建时更加轻松,它使您能够处理临时和永久复合构建,以及组合不同的构建并将复合构建导入 IntelliJ IDEA 的 Eclipse。
就执行模型而言,两者都有任务组和描述。两者都使您能够仅构建指定的项目及其依赖项。然而,Gradle 有一个完全可配置的 DAG,而使用 Maven,一个目标只能附加到另一个目标。多个目标采用有序列表的形式。Gradle 还允许任务排除、传递排除和任务依赖推断。Gradle 还具有用于任务排序和终结器等的高级功能。
管理构建基础设施是 Gradle 的另一个优势,因为它使用接受自动配置的包装器,而使用 Maven,您需要有一个扩展来支持自配置构建。Gradle 还使您能够配置基于版本的构建环境,而无需手动设置这些环境。它还允许自定义分发。
4
代码示例
在比较 Ant、Gradle 和 Maven 时,Naresh Joshi 比较了在Programming Mitra 中创建编译、执行静态分析、运行单元测试和创建 JAR 文件的构建脚本所需的代码。
以下是使用 Maven 实现此目的所需的代码:
代码语言:javascript复制<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.programming.mitra</groupId>
<artifactId>java-build-tools</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
</plugin>
</plugins>
</build>
</project>
要运行创建 JAR 文件的 Maven 目标,您将执行以下命令:
代码语言:javascript复制mvn package
请注意,使用此代码,您正在设置参数,但未指定必须执行的任务。您可以添加插件(例如 Maven CheckStyle、FindBugs 和 PMD)以将静态分析作为单个目标与单元测试一起执行,但您需要指定海关检查样式配置的路径以确保它在错误时失败,使用如下代码:
代码语言:javascript复制<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.12.1</version>
<executions>
<execution>
<configuration>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.5.4</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.1</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
要运行实现此目标的目标,请执行以下操作:
代码语言:javascript复制mvn verify
它需要相当多的 XML 代码来完成一些基本和常见的任务,因此,Maven 中具有大量任务和依赖项的项目可能会导致 pom.xml 文件包含数百到数千行代码。
为了比较,下面是一个实现类似结果的 build.gradle 代码示例:
代码语言:javascript复制apply plugin:'java'
apply plugin:'checkstyle'
apply plugin:'findbugs'
apply plugin:'pmd'
version ='1.0'
repositories {
mavenCentral()
}
dependencies {
testCompile group:'junit', name:'junit', version:'4.11'
}
这段代码更短,并且还引入了一些有用的任务,这些任务没有包含在上面的 Maven 代码中。执行以下命令以获取 Gradle 可以使用当前配置运行的任务列表:
代码语言:javascript复制gradle tasks --all
5
如何选择
总体而言,这两种工具都有各自的优点和缺点。
- 定制的构建。使用 Maven,您可以轻松定义项目的元数据和依赖项,但创建高度自定义的构建对于 Maven 用户来说可能是一场噩梦。随着项目的增长,POM 文件很容易变得臃肿,并且以后可能会成为不可读的 XML 文件。
- 依赖管理和目录结构。尽管如此,Maven 提供了简单而有效的依赖管理,并且由于它为您的项目提供了目录结构,因此您对所有项目都有某种标准布局。它为其 POM 文件使用声明性 XML 文件,并具有许多您可以使用的插件。Gradle 使用您在 Maven 上看到的目录结构,但这可以自定义。它还使用 Maven 用于识别工件的相同 GAV 格式。
- 插件和集成。Maven 还支持各种构建生命周期步骤,并与第三方工具无缝集成,例如 CI 服务器、代码覆盖插件和工件存储库系统等。就插件而言,现在有越来越多的可用插件,并且有大型供应商拥有与 Gradle 兼容的插件。但是,与 Gradle 可用的数量相比,Maven 可用的插件仍然更多。
- 灵活性。另一方面,Gradle 非常灵活并且基于脚本。在 Gradle 上自定义构建很容易。但是,由于 Gradle实际上是一个新手,因此了解 Gradle 的开发人员数量可能会受到限制。
最后,您选择什么将主要取决于您的需求。Gradle 更强大。但是,有时您确实不需要它提供的大多数特性和功能。Maven 可能最适合小型项目,而 Gradle 最适合大型项目。如果您一直在使用 Maven 并发现您的项目已经超出了它,那么可以从 Maven 迁移到 Gradle。
译文:dzone.com/articles/gradle-vs-maven