◉◡◉ 您好,欢迎到访伊成个人站!

Java中三大构建工具的发展历程(Ant、Maven和Gradle)

背景

我们要写一个Java程序,一般的步骤是编译,测试,打包。

这个构建的过程,如果文件比较少,我们可以手动使用java, javac,jar命令去做这些事情。但当工程越来越大,文件越来越多,这个事情就不是那么地令人开心了。

因为这些命令往往都是很机械的操作。所以我们可以把这些机械的操作交给机器去做。

而在linux中,有一个工具叫make。
我们可以通过编写Makefile来执行工程的构建,在windows上相应的工具是nmake。

那既然有现成的工具,为什么当时没有选择Makefile呢?说道这里那就不得不提一下Ant了。

Ant

说起Ant,就不得不说另一个Apache开源项目Tomcat。Tomcat作为轻量级Web容器,早已声名鹊起。最开始的时候,Ant是Tomcat的一部分,Ant的唯一目的就是build Tomcat。

不久,很多Java开源项目意识到Ant的简洁适用,更重要的是弥补Makefiles的不足。自从Jakarta以及Apache项目开始采用Ant以来,作为构建工具的Ant很快发展在各种各样的项目中。

在2000年1月,Ant脱离了Tomcat,成为独立的Apache开源项目,由独立的CVS模块维护,正式更名为Apache Ant。

第一个Ant版本是Tomcat 3.1于2000年4月19日发行的版本。此版本后来称为Ant 0.3.1。

到目前Ant最新的版本是 2020年5月13日 版本号:1.10.8

具体的版本发行历程可点击链接查看 http://ant.apache.org/faq.html

Ant示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8" ?>  
<project name="HelloWorld" default="run" basedir=".">
<property name="src" value="src"/>
<property name="dest" value="classes"/>
<property name="jarfile" value="hello.jar"/>
<target name="init">
<mkdir dir="${dest}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${dest}"/>
</target>
<target name="build" depends="compile">
<jar jarfile="${jarfile}" basedir="${dest}"/>
</target>
<target name="test" depends="build">
<java classname="test.ant.HelloWorld" classpath="${hello_jar}"/>
</target>
<target name="clean">
<delete dir="${dest}" />
<delete file="${hello_jar}" />
</target>
</project>

由示例,得知Ant定义了五个任务,init, compile, build, test,clean。

每个任务做什么都定义清楚了。在打包之前要先编译,所以通过depends来指定依赖的路径。

如果在命令行里执行ant build,那就会先执行compile,而compile又依赖于init,所以就会先执行init。

执行命令:

1
ant test

通过命令就可以执行编程,打包,测试。为开发者带来了很大的便利,提供了工作效率。

但是Ant有一个很致命的缺陷,那就是没办法管理依赖。

我们一个工程,要使用很多第三方工具,不同的工具,不同的版本。

每次打包都要自己手动去把正确的版本拷到lib下面去,不用说,这个工作既枯燥还特别容易出错。为了解决这个问题,Maven如约而至。

Maven

Maven之前我们经常使用Ant来进行Java项目的构建,然后Ant仅是一个构建工具,它并未对项目的中的工程依赖以及项目本身进行管理,并且Ant作为构建工具未能消除软件构建的重复性,因为不同的项目需要编写对应的Ant任务。

Maven作为后来者,继承了Ant的项目构建功能,并且提供了依赖关系,项目管理的功能,因此它是一个项目管理和综合工具, 其核心的依赖管理, 项目信息管理, 中央仓库,约定大于配置的核心功能使得Maven成为当前Java项目构建和管理工具的标准选择。

Maven 发展历程: Maven –> Maven2 –> Maven3

到目前Maven最新的版本是 2019-11-25 版本号:3.6.3

Maven示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<project ...xmlns...>
<groupId>net.devcheng.demo</groupId>
<artifactId>Example</artifactId>
<version>0.1.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>

由示例得知,包的坐标是net.devcheng.demo:Example:0.1.0-SNAPSHOT,而工程中要依赖junit:junit:4.10。

那么Maven就会自动去帮我把junit打包进来。如果本地没有junit,maven还会帮自动去网上下载。我们还通过Maven安装目录下的settings.xml文件可以配置本地仓库的路径,以及采用的远程仓库的地址。

相对于上文中的Ant来说,Maven抛弃了Ant中通过target定义任务的做法,对于依赖引入了生命周期。

最后在说说 Gradle。

Gradle

Gradle是一个基于Apache Ant和ApacheMaven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,目前也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。

由以上定义得知,Gradle已经抛弃了Ant,Maven中Xml配置的形式。Gradle继承了Maven中仓库,坐标,依赖这些核心概念。文件的布局也和Maven相同。但同时,又继承了Ant中target的概念,我们又可以重新定义自己的任务(在Gradle中叫做task)。

Gradle示例

1
2
3
4
5
6
7
8
9
10
11
apply plugin: 'java'

repositories {
jcenter()
}

dependencies {
compile 'org.slf4j:slf4j-api:1.7.21'
your tests.
testCompile 'junit:junit:4.12'
}

由示例可看出内容很简单,引入了java插件,指定仓库,指定依赖。可以看到依赖的设定相比起xml的写法,变得大大简化了。

到目前Gradle最新的版本是 2020年6月2日 版本号:v6.5

Gradle vs Maven

关于Gradle和Maven的区别,简单比较如下:

  • Maven和Gradle对依赖项的scope有所不同。
    在Maven世界中,一个依赖项有6种scope,分别是complie(默认)、provided、runtime、test、system、import。
    而grade将其简化为了4种,compile、runtime、testCompile、testRuntime。

  • Gradle支持动态的版本依赖。在版本号后面使用+号的方式可以实现动态的版本管理。

  • 解决依赖冲突方面Gradle的实现机制更加明确。使用Maven和Gradle进行依赖管理时都采用的是传递性依赖;而如果多个依赖项指向同一个依赖项的不同版本时就会引起依赖冲突。而Maven处理这种依赖关系往往是噩梦一般的存在。而Gradle在解决依赖冲突方面相对来说比较明确。
  • Maven引用依赖方面采用的xml,而Gradle不是。

The End
支付宝打赏 微信打赏