Gradle与Maven 在构建自动化工具方面,是两大重量级工具。看看他们各自的优缺点,并了解如何使用他们。

1 Gradle与Maven的概论

Gradle 是Stackify 的Comprehensive Java Developer’s Guide中介绍的几种Java 开发工具之一,但它并不是唯一要考虑的构建自动化工具。Maven 是一种较旧且常用的替代方案,但哪种构建系统最适合您的项目?使用Spring等其他工具,开发人员可以在两个系统之间进行选择,再加上两者的集成数量不断增加,决定权在很大程度上取决于您。

项目的大小、自定义需求以及其他一些变量可以帮助您做出选择。让我们来看看。

1.1 Gradle

Gradle是一个完全开源的构建自动化系统,它使用您在 Apache Maven 和 Apache Ant 上看到的概念。它使用基于编程语言Groovy的领域特定语言,与使用 XML 进行项目配置的 Apache Maven 不同。它还使用有向无环图确定任务运行的顺序。

几位开发人员创建了 Gradle,并于 2007 年首次发布,并于 2013 年被谷歌用作 Android 项目的构建系统。它旨在支持预计非常庞大的多项目构建。它还允许增量添加到您的构建中,因为它知道您的项目的哪些部分已更新。不再重新执行依赖于更新部件的任务。目前最新的稳定版本是2017年2月上线的3.4版本,支持使用Java、Scala、Groovy进行开发和后续部署,未来会陆续引入其他项目流程和语言。

1.2 Maven

Maven用于使用 Java 进行项目构建自动化。它可以帮助您了解特定软件的构建方式及其不同的依赖关系。它使用 XML 文件来描述您正在构建的项目、软件对第三方模块和部件的依赖性、构建顺序以及所需的插件。打包和编译等任务有预定义的目标。

Maven 将从不同的存储库下载库和插件,然后将它们全部放入本地计算机的缓存中。虽然主要用于 Java 项目,但您也可以将其用于 Scala、Ruby 和 C#,以及许多其他语言。

2 Gradle与Maven的比较

这两种系统方法的构建方式存在一些根本差异。Gradle 基于任务依赖关系图——其中任务是完成工作的事物——而 Maven 基于固定的线性阶段模型。在 Maven 中,目标附加到项目阶段,并且目标的功能与 Gradle 的任务类似,是“完成工作的东西”。

在性能方面,两者都允许多模块构建并行运行。但是,Gradle 允许增量构建,因为它会检查哪些任务已更新或未更新。如果是,则不会执行任务,从而大大缩短构建时间。您可以在 Gradle 上找到的其他显着性能特征包括:

  • Java 类的增量编译
  • Java 的编译规避
  • API 用于增量子任务
  • 一个编译器守护进程,也使编译速度更快

在依赖管理方面,Gradle 和 Maven 都可以处理动态和传递依赖,使用第三方依赖缓存,读取 POM 元数据格式。您还可以通过中央版本控制定义声明库版本并强制执行中央版本控制。两者都从它们的工件存储库中下载传递依赖项。Maven 有 Maven Central 而 Gradle 有 JCenter,你也可以定义自己的私人公司仓库。如果需要多个依赖项,Maven 可以同时下载这些依赖项。

然而,Gradle 在 API 和实现依赖性方面胜出,并且本质上允许并发安全缓存。它还将存储库元数据与缓存的依赖项一起保存,确保使用相同缓存的两个或多个项目不会相互覆盖,并且它具有基于校验和的缓存并且可以将缓存与存储库同步。此外,Gradle 兼容 IVY Metadata,允许您定义自定义规则以指定动态依赖的版本,并解决版本冲突。这些在 Maven 上不可用。

您只能在 Gradle 上找到的其他依赖项管理功能是:

  • 兼容库的替换规则的使用
  • ReplacedBy规则的使用
  • 更好的元数据分辨率
  • 能够用外部依赖项动态替换项目依赖项,反之亦然

Gradle 还让您在使用复合构建时更轻松,它使您能够使用临时和永久复合构建,以及组合不同的构建并将复合构建导入 IntelliJ IDEA 的 Eclipse。

就执行模型而言,两者都有任务组和描述。两者都使您能够仅构建指定的项目及其依赖项。然而,Gradle 有一个完全可配置的 DAG,而使用 Maven,一个目标只能附加到另一个目标。多个目标采用有序列表的形式。Gradle 还允许任务排除、传递排除和任务依赖关系推断。Gradle 还具有用于任务排序和终结器等的高级功能。

管理构建基础设施是 Gradle 的另一个强项,因为它使用接受自动配置的包装器,而对于 Maven,您需要有一个扩展来支持自配置构建。Gradle 还使您能够配置基于版本的构建环境,而无需手动设置这些环境。它还允许自定义分发。

Gradle与Maven的代码示例

在 Ant、Gradle 和 Maven 的比较中,Naresh Joshi 在Programming Mitra 中比较了创建编译、执行静态分析、运行单元测试和创建 JAR 文件的构建脚本所需的代码。

这是使用 Maven 实现此目的所需的代码:

<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 目标,您将执行以下命令:

mvn package

请注意,使用此代码时,您是在设置参数,但并未指定必须执行的任务。您可以添加插件(如 Maven CheckStyle、FindBugs 和 PMD)以将静态分析作为单个目标与单元测试一起执行,但您需要指定海关检查样式配置的路径以确保它在错误时失败,使用如下代码:

<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>

要运行实现此目标的目标,请执行以下操作:

mvn verify

它需要相当多的 XML 代码来实现一些基本和常见的任务,因此,Maven 中具有大量任务和依赖项的项目可能会导致 pom.xml 文件包含数百至数千行代码。

为了进行比较,下面是一个实现类似结果的 build.gradle 代码示例:

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'
}
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 可以使用当前配置运行的任务列表:

gradle tasks --all

Gradle与Maven如何选择

总的来说,这两种工具都有各自的优点和缺点。

  • 定制构建。 使用 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

相关文章

使用Maven进行单元测试

创建Maven原型

Maven构建前端资源