Ant 和 Maven 之间的区别

发布于 2024-07-14 22:34:45 字数 1437 浏览 10 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

剪不断理还乱 2024-07-21 22:34:45

Maven:权威指南中,我写了关于Maven 和 Ant 之间的差异在介绍部分标题是 “Ant 和 Maven 之间的区别”。 这是一个答案,该答案结合了该简介中的信息和一些附加注释。

简单比较

我向您展示这一点只是为了说明这样一个想法:在最基本的层面上,Maven 具有内置约定。 下面是一个简单的 Ant 构建文件:

<project name="my-project" default="dist" basedir=".">
    <description>
        simple example build file
    </description>   
    <!-- set global properties for this build -->   
    <property name="src" location="src/main/java"/>
    <property name="build" location="target/classes"/>
    <property name="dist"  location="target"/>

    <target name="init">
      <!-- Create the time stamp -->
      <tstamp/>
      <!-- Create the build directory structure used by compile -->
      <mkdir dir="${build}"/>   
    </target>

    <target name="compile" depends="init"
        description="compile the source " >
      <!-- Compile the java code from ${src} into ${build} -->
      <javac srcdir="${src}" destdir="${build}"/>  
    </target>

    <target name="dist" depends="compile"
        description="generate the distribution" >
      <!-- Create the distribution directory -->
      <mkdir dir="${dist}/lib"/>

      <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file
-->
      <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
   </target>

   <target name="clean"
        description="clean up" >
     <!-- Delete the ${build} and ${dist} directory trees -->
     <delete dir="${build}"/>
     <delete dir="${dist}"/>
   </target>
 </project>

在这个简单的 Ant 示例中,您可以看到如何必须准确地告诉 Ant 要做什么。 有一个编译目标,其中包括 javac 任务,该任务将 src/main/java 目录中的源代码编译到 target/classes 目录。 您必须准确地告诉 Ant 您的源代码在哪里,您希望将生成的字节码存储在哪里,以及如何将所有这些打包到 JAR 文件中。 虽然最近的一些进展有助于减少 Ant 的过程性,但开发人员使用 Ant 的经验是用 XML 编写过程性语言。

将前面的 Ant 示例与 Maven 示例进行对比。 在 Maven 中,要从某个 Java 源创建 JAR 文件,您所需要做的就是创建一个简单的 pom.xml,将源代码放在 ${basedir}/src/main/java 中,然后从命令行运行 mvn install 。 示例 Maven pom.xml 实现了相同的结果。

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0</version>
</project>

这就是您在 pom.xml 中所需要的全部内容。 从命令行运行 mvn install 将处理资源、编译源代码、执行单元测试、创建 JAR 并将 JAR 安装在本地存储库中以便在其他项目中重用。 无需修改,您可以运行 mvn site,然后在 target/site 中找到一个 index.html 文件,其中包含指向 JavaDoc 的链接以及一些有关源代码的报告。

诚然,这是最简单的示例项目。 一个仅包含源代码并生成 JAR 的项目。 遵循 Maven 约定且不需要任何依赖项或自定义的项目。 如果我们想开始自定义行为,我们的 pom.xml 的大小将会增加,并且在最大的项目中,您可以看到非常复杂的 Maven POM 集合,其中包含大量插件自定义和依赖项声明。 但是,即使您的项目的 POM 文件变得更加庞大,它们所包含的信息也与使用 Ant 的类似大小的项目的构建文件完全不同。 Maven POM 包含声明:“这是一个 JAR 项目”和“源代码位于 src/main/java 中”。 Ant 构建文件包含明确的指令:“这是项目”、“源代码位于 src/main/java”、“针对此目录运行 javac”、“将结果是 target/classses”、“从 .... 创建一个 JAR”等。在 Ant 必须明确该过程的地方,Maven 有一些“内置”的东西,只需知道源代码在哪里以及应该如何处理它。

高层比较

本例中 Ant 和 Maven 之间的差异? Ant...

  • 没有像公共项目目录结构这样的正式约定,您必须准确地告诉 Ant 在哪里找到源代码以及在哪里放置输出。 随着时间的推移,非正式约定已经出现,但它们尚未被编入产品中。
  • 是程序性的,你必须准确地告诉Ant要做什么以及何时做。 你必须告诉它编译,然后复制,然后压缩。
  • 没有生命周期,您必须定义目标和目标依赖性。 您必须手动将一系列任务附加到每个目标。

Maven...

  • 有约定,它已经知道你的源代码在哪里,因为你遵循了约定。 它将字节码放入 target/classes 中,并在 target 中生成一个 JAR 文件。
  • 是声明性的。 您所要做的就是创建一个 pom.xml 文件并将源代码放入默认目录中。 Maven 负责剩下的事情。
  • 有一个生命周期,您在执行 mvn install 时调用它。 该命令告诉 Maven 执行一系列顺序步骤,直到到达生命周期。 作为整个生命周期旅程的副作用,Maven 执行了许多默认插件目标,这些目标执行诸如编译和创建 JAR 之类的操作。

艾维怎么样?

是的,所以像史蒂夫·洛夫兰这样的人会读到这个比较并认为犯规。 他将讨论答案如何完全忽略称为 Ivy 的东西,以及 Ant 可以在更新的 Ant 版本中重用构建逻辑的事实。 这是真实的。 如果你有一群聪明的人使用 Ant + antlibs + Ivy,你最终会得到一个设计良好且有效的构建。 尽管如此,我非常相信 Maven 是有意义的,但我很乐意与一个拥有非常敏锐的构建工程师的项目团队一起使用 Ant + Ivy。 话虽这么说,我确实认为您最终会错过许多有价值的插件,例如 Jetty 插件,并且随着时间的推移,您最终会完成一大堆不需要做的工作。

比 Maven 与 Ant 更重要的

  1. 是您使用存储库管理器来跟踪软件工件。 我建议下载 Nexus。 您可以使用 Nexus 代理远程存储库,并为您的团队提供部署内部工件的位置。
  2. 您对软件组件进行了适当的模块化。 一个大的整体组件很少会随着时间的推移而扩展。 随着项目的发展,您将需要拥有模块和子模块的概念。 Maven 非常适合这种方法。
  3. 您为您的构建采用一些约定。 即使您使用 Ant,您也应该努力采用某种与其他项目一致的约定形式。 当一个项目使用 Maven 时,这意味着任何熟悉 Maven 的人都可以选择构建并开始运行它,而不必为了弄清楚如何编译而摆弄配置。

In Maven: The Definitive Guide, I wrote about the differences between Maven and Ant in the introduction the section title is "The Differences Between Ant and Maven". Here's an answer that is a combination of the info in that introduction with some additional notes.

A Simple Comparison

I'm only showing you this to illustrate the idea that, at the most basic level, Maven has built-in conventions. Here's a simple Ant build file:

<project name="my-project" default="dist" basedir=".">
    <description>
        simple example build file
    </description>   
    <!-- set global properties for this build -->   
    <property name="src" location="src/main/java"/>
    <property name="build" location="target/classes"/>
    <property name="dist"  location="target"/>

    <target name="init">
      <!-- Create the time stamp -->
      <tstamp/>
      <!-- Create the build directory structure used by compile -->
      <mkdir dir="${build}"/>   
    </target>

    <target name="compile" depends="init"
        description="compile the source " >
      <!-- Compile the java code from ${src} into ${build} -->
      <javac srcdir="${src}" destdir="${build}"/>  
    </target>

    <target name="dist" depends="compile"
        description="generate the distribution" >
      <!-- Create the distribution directory -->
      <mkdir dir="${dist}/lib"/>

      <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file
-->
      <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
   </target>

   <target name="clean"
        description="clean up" >
     <!-- Delete the ${build} and ${dist} directory trees -->
     <delete dir="${build}"/>
     <delete dir="${dist}"/>
   </target>
 </project>

In this simple Ant example, you can see how you have to tell Ant exactly what to do. There is a compile goal which includes the javac task that compiles the source in the src/main/java directory to the target/classes directory. You have to tell Ant exactly where your source is, where you want the resulting bytecode to be stored, and how to package this all into a JAR file. While there are some recent developments that help make Ant less procedural, a developer's experience with Ant is in coding a procedural language written in XML.

Contrast the previous Ant example with a Maven example. In Maven, to create a JAR file from some Java source, all you need to do is create a simple pom.xml, place your source code in ${basedir}/src/main/java and then run mvn install from the command line. The example Maven pom.xml that achieves the same results.

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0</version>
</project>

That's all you need in your pom.xml. Running mvn install from the command line will process resources, compile source, execute unit tests, create a JAR, and install the JAR in a local repository for reuse in other projects. Without modification, you can run mvn site and then find an index.html file in target/site that contains links to JavaDoc and a few reports about your source code.

Admittedly, this is the simplest possible example project. A project which only contains source code and which produces a JAR. A project which follows Maven conventions and doesn't require any dependencies or customization. If we wanted to start customizing the behavior, our pom.xml is going to grow in size, and in the largest of projects you can see collections of very complex Maven POMs which contain a great deal of plugin customization and dependency declarations. But, even when your project's POM files become more substantial, they hold an entirely different kind of information from the build file of a similarly sized project using Ant. Maven POMs contain declarations: "This is a JAR project", and "The source code is in src/main/java". Ant build files contain explicit instructions: "This is project", "The source is in src/main/java", "Run javac against this directory", "Put the results in target/classses", "Create a JAR from the ....", etc. Where Ant had to be explicit about the process, there was something "built-in" to Maven that just knew where the source code was and how it should be processed.

High-level Comparison

The differences between Ant and Maven in this example? Ant...

  • doesn't have formal conventions like a common project directory structure, you have to tell Ant exactly where to find the source and where to put the output. Informal conventions have emerged over time, but they haven't been codified into the product.
  • is procedural, you have to tell Ant exactly what to do and when to do it. You had to tell it to compile, then copy, then compress.
  • doesn't have a lifecycle, you had to define goals and goal dependencies. You had to attach a sequence of tasks to each goal manually.

Where Maven...

  • has conventions, it already knew where your source code was because you followed the convention. It put the bytecode in target/classes, and it produced a JAR file in target.
  • is declarative. All you had to do was create a pom.xml file and put your source in the default directory. Maven took care of the rest.
  • has a lifecycle, which you invoked when you executed mvn install. This command told Maven to execute a series of sequence steps until it reached the lifecycle. As a side-effect of this journey through the lifecycle, Maven executed a number of default plugin goals which did things like compile and create a JAR.

What About Ivy?

Right, so someone like Steve Loughran is going to read that comparison and call foul. He's going to talk about how the answer completely ignores something called Ivy and the fact that Ant can reuse build logic in the more recent releases of Ant. This is true. If you have a bunch of smart people using Ant + antlibs + Ivy, you'll end up with a well designed build that works. Even though, I'm very much convinced that Maven makes sense, I'd happily use Ant + Ivy with a project team that had a very sharp build engineer. That being said, I do think you'll end up missing out on a number of valuable plugins such as the Jetty plugin and that you'll end up doing a whole bunch of work that you didn't need to do over time.

More Important than Maven vs. Ant

  1. Is that you use a Repository Manager to keep track of software artifacts. I'd suggest downloading Nexus. You can use Nexus to proxy remote repositories and to provide a place for your team to deploy internal artifacts.
  2. You have appropriate modularization of software components. One big monolithic component rarely scales over time. As your project develops, you'll want to have the concept of modules and sub-modules. Maven lends itself to this approach very well.
  3. You adopt some conventions for your build. Even if you use Ant, you should strive to adopt some form of convention that is consistent with other projects. When a project uses Maven, it means that anyone familiar with Maven can pick up the build and start running with it without having to fiddle with configuration just to figure out how to get the thing to compile.
情何以堪。 2024-07-21 22:34:45

Maven 是一个框架,Ant 是一个工具箱

Maven 是一辆预先构建的公路汽车,而 Ant 是一组汽车部件。 使用 Ant,你必须建造自己的汽车,但至少如果你需要进行任何越野驾驶,你可以建造合适类型的汽车。

换句话说,Maven 是一个框架,而 Ant 是一个工具箱。 如果您满足于在框架范围内工作,那么 Maven 就可以了。 对我来说,问题是我不断地碰触框架的界限,它不让我出去。

XML Verbosity

tobrien 是一个非常了解 Maven 的人,我认为他对这两种产品提供了非常好的、诚实的比较。 他将简单的 Maven pom.xml 与简单的 Ant 构建文件进行了比较,并提到了 Maven 项目如何变得更加复杂。 我认为值得看一下您在简单的实际项目中更可能看到的几个文件的比较。 下面的文件代表多模块构建中的单个模块。

首先,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-4_0_0.xsd">

    <parent>
        <groupId>com.mycompany</groupId>
        <artifactId>app-parent</artifactId>
        <version>1.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>persist</artifactId>
    <name>Persistence Layer</name>

    <dependencies>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>common</artifactId>
            <scope>compile</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>domain</artifactId>
            <scope>provided</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate</artifactId>
            <version>${hibernate.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>${commons-lang.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>2.2.3</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${commons-dbcp.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc</artifactId>
            <version>${oracle-jdbc.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>${easymock.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

以及等效的 Ant 文件:

<project name="persist" >

    <import file="../build/common-build.xml" />


    <path id="compile.classpath.main">
        <pathelement location="${common.jar}" />
        <pathelement location="${domain.jar}" />
        <pathelement location="${hibernate.jar}" />
        <pathelement location="${commons-lang.jar}" />
        <pathelement location="${spring.jar}" />
    </path>


    <path id="compile.classpath.test">
        <pathelement location="${classes.dir.main}" />
        <pathelement location="${testng.jar}" />
        <pathelement location="${dbunit.jar}" />
        <pathelement location="${easymock.jar}" />
        <pathelement location="${commons-dbcp.jar}" />
        <pathelement location="${oracle-jdbc.jar}" />
        <path refid="compile.classpath.main" />
    </path>


    <path id="runtime.classpath.test">
        <pathelement location="${classes.dir.test}" />
        <path refid="compile.classpath.test" />
    </path>


</project>

tobrien 使用他的示例来表明 Maven 具有内置约定,但这并不一定意味着您最终会编写更少的 XML。 我发现事实恰恰相反。 pom.xml 比 build.xml 长 3 倍,这并没有偏离约定。 事实上,我的 Maven 示例没有显示配置插件所需的额外 54 行。 该 pom.xml 适用于一个简单的项目。 当您开始添加额外的需求时,XML 确实开始显着增长,这对于许多项目来说并不罕见。

但是你必须告诉 Ant 做什么

当然,上面的 Ant 示例并不完整。 我们仍然必须定义用于清理、编译、测试等的目标。这些目标是在由多模块项目中的所有模块导入的通用构建文件中定义的。 这让我想到了所有这些东西如何必须在 Ant 中显式编写,而在 Maven 中是声明性的。

确实如此,如果我不必显式编写这些 Ant 目标,将会节省我的时间。 但要花多少时间呢? 我现在使用的通用构建文件是我 5 年前编写的,此后仅进行了一些细微的改进。 经过 2 年的 Maven 实验后,我把旧的 Ant 构建文件从柜子里拿出来,掸去灰尘,然后重新投入工作。 对我来说,在 5 年的时间里,必须明确告诉 Ant 做什么的成本加起来不到一周。

复杂性

我想提到的下一个主要区别是复杂性及其对现实世界的影响。 构建 Maven 的目的是减少负责创建和管理构建流程的开发人员的工作量。 为了做到这一点,它必须很复杂。 不幸的是,这种复杂性往往会否定他们的预期目标。

与 Ant 相比,Maven 项目的构建人员会花费更多的时间:

  • 阅读文档:关于 Maven 的文档要多得多,因为您需要学习的东西太多了。
  • 教育团队成员:他们发现询问了解的人比尝试自己寻找答案更容易。
  • 构建故障排除:Maven 不如 Ant 可靠,尤其是非核心插件。 此外,Maven 构建是不可重复的。 如果您依赖插件的快照版本(这很可能是),您的构建可能会在您不进行任何更改的情况下中断。
  • 编写 Maven 插件:插件通常是根据特定任务来编写的,例如创建一个 webstart 包,这使得将它们重用于其他任务或将它们组合起来以实现目标变得更加困难。 因此,您可能必须编写自己的插件来解决现有插件集中的差距。

相比之下:

  • Ant 文档简洁、全面且全部集中在一处。
  • 蚂蚁很简单。 尝试学习 Ant 的新开发人员只需要了解一些简单的概念(目标、任务、依赖项、属性),就能够弄清楚他们需要了解的其余内容。
  • 蚂蚁靠谱。 在过去的几年里,Ant 的版本并不多,因为它已经可以工作了。
  • Ant 构建是可重复的,因为它们通常是在没有任何外部依赖项的情况下创建的,例如在线存储库、实验性第三方插件等。Ant
  • 很全面。 因为它是一个工具箱,所以您可以组合这些工具来执行几乎任何您想要的任务。 如果您需要编写自己的自定义任务,则非常简单。

熟悉度

另一个区别是熟悉度。 新的开发人员总是需要时间来跟上进度。 熟悉现有产品在这方面有所帮助,Maven 支持者正确地声称这是 Maven 的一个好处。 当然,Ant 的灵活性意味着您可以创建任何您喜欢的约定。 所以我使用的约定是将源文件放在名为 src/main/java 的目录中。 我编译的类进入名为 target/classes 的目录。 听起来很熟悉不是吗。

我喜欢 Maven 使用的目录结构。 我认为这是有道理的。 还有他们的构建生命周期。 所以我在 Ant 构建中使用相同的约定。 不仅因为它有意义,而且因为以前使用过 Maven 的人都会熟悉它。

Maven is a Framework, Ant is a Toolbox

Maven is a pre-built road car, whereas Ant is a set of car parts. With Ant you have to build your own car, but at least if you need to do any off-road driving you can build the right type of car.

To put it another way, Maven is a framework whereas Ant is a toolbox. If you're content with working within the bounds of the framework then Maven will do just fine. The problem for me was that I kept bumping into the bounds of the framework and it wouldn't let me out.

XML Verbosity

tobrien is a guy who knows a lot about Maven and I think he provided a very good, honest comparison of the two products. He compared a simple Maven pom.xml with a simple Ant build file and he made mention of how Maven projects can become more complex. I think that its worth taking a look at a comparison of a couple of files that you are more likely to see in a simple real-world project. The files below represent a single module in a multi-module build.

First, the Maven file:

<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-4_0_0.xsd">

    <parent>
        <groupId>com.mycompany</groupId>
        <artifactId>app-parent</artifactId>
        <version>1.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>persist</artifactId>
    <name>Persistence Layer</name>

    <dependencies>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>common</artifactId>
            <scope>compile</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>domain</artifactId>
            <scope>provided</scope>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate</artifactId>
            <version>${hibernate.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>${commons-lang.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>${spring.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>2.2.3</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>${commons-dbcp.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc</artifactId>
            <version>${oracle-jdbc.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>${easymock.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

And the equivalent Ant file:

<project name="persist" >

    <import file="../build/common-build.xml" />


    <path id="compile.classpath.main">
        <pathelement location="${common.jar}" />
        <pathelement location="${domain.jar}" />
        <pathelement location="${hibernate.jar}" />
        <pathelement location="${commons-lang.jar}" />
        <pathelement location="${spring.jar}" />
    </path>


    <path id="compile.classpath.test">
        <pathelement location="${classes.dir.main}" />
        <pathelement location="${testng.jar}" />
        <pathelement location="${dbunit.jar}" />
        <pathelement location="${easymock.jar}" />
        <pathelement location="${commons-dbcp.jar}" />
        <pathelement location="${oracle-jdbc.jar}" />
        <path refid="compile.classpath.main" />
    </path>


    <path id="runtime.classpath.test">
        <pathelement location="${classes.dir.test}" />
        <path refid="compile.classpath.test" />
    </path>


</project>

tobrien used his example to show that Maven has built-in conventions but that doesn't necessarily mean that you end up writing less XML. I have found the opposite to be true. The pom.xml is 3 times longer than the build.xml and that is without straying from the conventions. In fact, my Maven example is shown without an extra 54 lines that were required to configure plugins. That pom.xml is for a simple project. The XML really starts to grow significantly when you start adding in extra requirements, which is not out of the ordinary for many projects.

But you have to tell Ant what to do

My Ant example above is not complete of course. We still have to define the targets used to clean, compile, test etc. These are defined in a common build file that is imported by all modules in the multi-module project. Which leads me to the point about how all this stuff has to be explicitly written in Ant whereas it is declarative in Maven.

Its true, it would save me time if I didn't have to explicitly write these Ant targets. But how much time? The common build file I use now is one that I wrote 5 years ago with only slight refinements since then. After my 2 year experiment with Maven, I pulled the old Ant build file out of the closet, dusted it off and put it back to work. For me, the cost of having to explicitly tell Ant what to do has added up to less than a week over a period of 5 years.

Complexity

The next major difference I'd like to mention is that of complexity and the real-world effect it has. Maven was built with the intention of reducing the workload of developers tasked with creating and managing build processes. In order to do this it has to be complex. Unfortunately that complexity tends to negate their intended goal.

When compared with Ant, the build guy on a Maven project will spend more time:

  • Reading documentation: There is much more documentation on Maven, because there is so much more you need to learn.
  • Educating team members: They find it easier to ask someone who knows rather than trying to find answers themselves.
  • Troubleshooting the build: Maven is less reliable than Ant, especially the non-core plugins. Also, Maven builds are not repeatable. If you depend on a SNAPSHOT version of a plugin, which is very likely, your build can break without you having changed anything.
  • Writing Maven plugins: Plugins are usually written with a specific task in mind, e.g. create a webstart bundle, which makes it more difficult to reuse them for other tasks or to combine them to achieve a goal. So you may have to write one of your own to workaround gaps in the existing plugin set.

In contrast:

  • Ant documentation is concise, comprehensive and all in one place.
  • Ant is simple. A new developer trying to learn Ant only needs to understand a few simple concepts (targets, tasks, dependencies, properties) in order to be able to figure out the rest of what they need to know.
  • Ant is reliable. There haven't been very many releases of Ant over the last few years because it already works.
  • Ant builds are repeatable because they are generally created without any external dependencies, such as online repositories, experimental third-party plugins etc.
  • Ant is comprehensive. Because it is a toolbox, you can combine the tools to perform almost any task you want. If you ever need to write your own custom task, it's very simple to do.

Familiarity

Another difference is that of familiarity. New developers always require time to get up to speed. Familiarity with existing products helps in that regard and Maven supporters rightly claim that this is a benefit of Maven. Of course, the flexibility of Ant means that you can create whatever conventions you like. So the convention I use is to put my source files in a directory name src/main/java. My compiled classes go into a directory named target/classes. Sounds familiar doesn't it.

I like the directory structure used by Maven. I think it makes sense. Also their build lifecycle. So I use the same conventions in my Ant builds. Not just because it makes sense but because it will be familiar to anyone who has used Maven before.

表情可笑 2024-07-21 22:34:45

Ant主要是一个构建工具。

Maven 是一个项目和依赖项管理工具(当然它也可以构建您的项目)。

如果您想避免 Maven,Ant+Ivy 是一个非常好的组合。

Ant is mainly a build tool.

Maven is a project and dependencies management tool (which of course builds your project as well).

Ant+Ivy is a pretty good combination if you want to avoid Maven.

与风相奔跑 2024-07-21 22:34:45

仅列出一些更多差异:

  • Ant 没有正式的约定。 您必须准确地告诉 Ant 在哪里找到源、在哪里放置输出等。Ant
  • 是程序性的。 你必须准确地告诉Ant要做什么; 告诉它编译、复制、然后压缩等。Ant
  • 没有生命周期。
  • Maven 使用约定。 只要您遵循这些约定,它就会自动知道您的源代码在哪里。 您不需要告诉 Maven 它在哪里。
  • Maven 是声明式的; 您所要做的就是创建一个 pom.xml 文件并将源代码放入默认目录中。 Maven 会处理剩下的事情。
  • Maven 有生命周期。 您只需调用 mvn install 即可执行一系列序列步骤。
  • Maven 具有关于常见项目任务的智能。 要运行测试,只需执行mvn test,只要文件位于默认位置即可。 在 Ant 中,您首先必须创建 JUnit JAR 文件,然后创建一个包含 JUnit JAR 的类路径,然后告诉 Ant 应在哪里查找测试源代码,编写编译测试源的目标,最后执行单元测试与 JUnit。

更新:

这来自Maven:权威指南。 抱歉,我完全忘了引用它。

Just to list some more differences:

  • Ant doesn't have formal conventions. You have to tell Ant exactly where to find the source, where to put the outputs, etc.
  • Ant is procedural. You have to tell Ant exactly what to do; tell it to compile, copy, then compress, etc.
  • Ant doesn't have a lifecycle.
  • Maven uses conventions. It knows where your source code is automatically, as long as you follow these conventions. You don't need to tell Maven where it is.
  • Maven is declarative; All you have to do is create a pom.xml file and put your source in the default directory. Maven will take care of the rest.
  • Maven has a lifecycle. You simply call mvn install and a series of sequence steps are executed.
  • Maven has intelligence about common project tasks. To run tests, simple execute mvn test, as long as the files are in the default location. In Ant, you would first have to JUnit JAR file is, then create a classpath that includes the JUnit JAR, then tell Ant where it should look for test source code, write a goal that compiles the test source and then finally execute the unit tests with JUnit.

Update:

This came from Maven: The Definitive Guide. Sorry, I totally forgot to cite it.

秉烛思 2024-07-21 22:34:45

Maven or Ant? 是一个与此非常相似的问题,它应该可以帮助您回答您的问题。

官方网站上的 什么是 Maven?

编辑:对于新的/未开发的项目,我建议使用 Maven:“约定优于配置”将为您节省大量编写和设置构建和部署脚本的时间。 当您使用 ant 时,构建脚本的长度和复杂性往往会随着时间的推移而增长。 对于现有项目,很难将其配置/布局硬塞到 Maven 系统中。

Maven or Ant? is a very similar question to this one, which should help you answer your questions.

What is Maven? on the official site.

edit: For a new/greenfield project, I'd recommend using Maven: "convention over configuration" will save you a decent chunk of time in writing and setting up build and deployment scripts. When you use ant, the build script tends to grow over time in length and complexity. For existing projects, it can be hard to shoehorn their configuration/layout into the Maven system.

冰雪梦之恋 2024-07-21 22:34:45

Maven 既充当依赖管理工具(它可用于从中央存储库或您设置的存储库检索 jar),又充当声明性构建工具。 “声明式”构建工具与 ant 或 make 等更传统的构建工具之间的区别在于您配置需要完成的内容,而不是配置完成的方式。 例如,您可以在 Maven 脚本中说,应该将项目打包为 WAR 文件,并且 Maven 知道如何处理该问题。

Maven 依赖于有关项目目录如何布局的约定,以实现其“声明性”。 例如,它有一个关于放置主代码、放置 web.xml、单元测试等的约定,但也提供了在需要时更改它们的能力。

您还应该记住,有一个用于从 maven 中运行 ant 命令的插件:

http://maven.apache.org/plugins/maven-ant-plugin/

另外,maven 的原型使得项目的启动速度非常快。 例如,有一个 Wicket 原型,它提供了一个 Maven 命令,您可以运行该命令来获取整个、准备运行的 hello world 类型项目。

https://wicket.apache.org/start/quickstart.html

Maven acts as both a dependency management tool - it can be used to retrieve jars from a central repository or from a repository you set up - and as a declarative build tool. The difference between a "declarative" build tool and a more traditional one like ant or make is you configure what needs to get done, not how it gets done. For example, you can say in a maven script that a project should be packaged as a WAR file, and maven knows how to handle that.

Maven relies on conventions about how project directories are laid out in order to achieve its "declarativeness." For example, it has a convention for where to put your main code, where to put your web.xml, your unit tests, and so on, but also gives the ability to change them if you need to.

You should also keep in mind that there is a plugin for running ant commands from within maven:

http://maven.apache.org/plugins/maven-ant-plugin/

Also, maven's archetypes make getting started with a project really fast. For example, there is a Wicket archetype, which provides a maven command you run to get a whole, ready-to-run hello world-type project.

https://wicket.apache.org/start/quickstart.html

情深如许 2024-07-21 22:34:45

我可以带一个从未见过 Ant 的人 - 它的 build.xml 写得相当好 - 他们可以理解发生了什么。 我可以带同一个人向他们展示 Maven POM,他们将不知道发生了什么。

在一个庞大的工程组织中,人们写到 Ant 文件变得很大并且难以管理。 我已经编写了这些类型干净的 Ant 脚本。 这实际上是预先了解您未来需要做什么,并设计一组可以响应 3 年以上的变化和规模的模板。

除非您有一个简单的项目,否则学习 Maven 约定和 Maven 完成工作的方法是一项相当大的工作。

归根结底,您不能将使用 Ant 或 Maven 启动项目视为一个因素:它实际上是总拥有成本。 组织在几年内维护和扩展其构建系统所需的时间是必须考虑的主要因素之一。

构建系统最重要的方面是依赖管理和表达构建方案的灵活性。 如果做得好的话,它一定是有点直观的。

I can take a person that has never seen Ant - its build.xmls are reasonably well-written - and they can understand what is going on. I can take that same person and show them a Maven POM and they will not have any idea what is going on.

In an engineering organization that is huge, people write about Ant files becoming large and unmanageable. I've written those types and clean Ant scripts. It's really understanding upfront what you need to do going forward and designing a set of templates that can respond to change and scale over a 3+ year period.

Unless you have a simple project, learning the Maven conventions and the Maven way about getting things done is quite a bit of work.

At the end of the day you cannot consider project startup with Ant or Maven a factor: it's really the total cost of ownership. What it takes for the organization to maintain and extend its build system over a few years is one of the main factors that must be considered.

The most important aspects of a build system are dependency management and flexibility in expressing the build recipe. It must be somewhat intuitive when done well.

浪荡不羁 2024-07-21 22:34:45

我想说这取决于你的项目的大小...就我个人而言,我会使用 Maven 来处理需要直接编译、打包和部署的简单项目。 一旦您需要做一些更复杂的事情(许多依赖项、创建映射文件...),我就会切换到 Ant...

I'd say it depends upon the size of your project... Personnally, I would use Maven for simple projects that need straightforward compiling, packaging and deployment. As soon as you need to do some more complicated things (many dependencies, creating mapping files...), I would switch to Ant...

但可醉心 2024-07-21 22:34:45

Maven 还拥有一个大型的常用开源项目存储库。 在构建过程中,Maven 可以为您下载这些依赖项(以及您的依赖项依赖项:)),以使构建项目的这一部分更易于管理。

Maven also houses a large repository of commonly used open source projects. During the build Maven can download these dependencies for you (as well as your dependencies dependencies :)) to make this part of building a project a little more manageable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文