Maven 对常见的项目任务很有研究。要运行测试,只要文件位于默认位置,就执行 Mvn 测试。在 Ant 中,首先必须使用 JUnit JAR 文件 is,然后创建一个包含 JUnit JAR 的类路径,然后告诉 Ant 应该在哪里查找测试源代码,编写一个目标来编译测试源代码,最后用 JUnit 执行单元测试。
我给你们看这个只是为了说明这个想法,在最基本的层面上,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。
不可否认,这是最简单的示例项目。只包含源代码并生成 JAR 的项目。遵循 Maven 约定的项目,不需要任何依赖关系或自定义。如果我们想开始定制行为,我们的 pom.xml 会变大,在最大的项目中,你可以看到非常复杂的 Maven POM 集合,它包含了大量的插件定制和依赖声明。但是,即使您的项目的 POM 文件变得更加重要,它们仍然保存着与使用 Ant 的类似大小的项目的构建文件完全不同的信息。Maven POM 包含声明: “ This is a JAR project”和“ The source code is in src/main/java”。Ant 构建文件包含明确的指令: “ This is project”、“ The source is in src/main/java”、“ Run javac against This directory”、“ Put The result in target/classses”、“ Create a JAR from The...”等等。在 Ant 必须明确说明流程的地方,Maven 有一些“内置”的东西,它只知道源代码在哪里,以及应该如何处理它。
高级别比较
在这个例子中,Ant 和 Maven 之间的区别是什么。
没有像通用项目目录结构那样的正式约定,你必须准确地告诉 Ant 在哪里可以找到源代码,在哪里可以放置输出。随着时间的推移,非正式的约定出现了,但它们还没有被编入产品。
是程序性的,您必须确切地告诉 Ant 要做什么和什么时候做。你必须告诉它编译,然后复制,然后压缩。
没有生命周期,你必须定义目标和目标依赖关系。您必须手动将一系列任务附加到每个目标。
玛文..。
它已经知道你的源代码在哪里,因为你遵循了约定。它将字节码放在 target/class 中,并在 target 中生成一个 JAR 文件。
没错,所以像 Steve Loughran 这样的人会读到这个比较,然后判犯规。他将谈到答案是如何完全忽略了常青藤(Ivy)这一概念,以及 Ant 可以在最近的 Ant 版本中重用构建逻辑这一事实。这倒是真的。如果你有一群使用 Ant + antlibs + Ivy 的聪明人,你最终会得到一个设计良好的可以工作的版本。尽管如此,我还是非常相信 Maven 是有意义的,我很乐意与一个拥有非常出色的构建工程师的项目团队一起使用 Ant + Ivy。也就是说,我确实认为你最终会错过一些有价值的插件,比如 Jetty 插件,你最终会做一大堆你不需要花时间去做的工作。
当然,我上面的 Ant 示例并不完整。我们仍然需要定义用于清理、编译、测试等的目标。这些是在由多模块项目中的所有模块导入的公共生成文件中定义的。这让我想到,所有这些东西都必须在 Ant 中显式编写,而在 Maven 中是声明性的。
这是真的,如果我不需要显式地编写这些 Ant 目标,它将节省我的时间。但还有多少时间?我现在使用的通用构建文件是我5年前编写的,从那时起只进行了一些细微的改进。在我用 Maven 做了两年的实验之后,我把旧的 Ant 构建文件从柜子里拿出来,掸去上面的灰尘,让它重新开始工作。对我来说,在5年的时间里,明确告诉 Ant 要做什么的成本加起来不到一周。