Maven简介 1.1何为Maven Maven这个词可以翻译为“知识的积累”,或者翻译成“专家”或“内行”。本书我们介绍Maven这一跨平台的项目管理工具。作为Apache组织中一个颇为成功的开源项目,Maven主要服务于基于Java平台的项目构建,依赖管理,项目信息管理。无论是小型的开源类库项目,或者是大型的企业级应用,无论是传统的瀑布式开发,或者是流行的敏捷模式,Maven都十分适用。 1.1.1 何为构建(Build) 不管你有没有意识到,构建是每个程序员每天都在做的工作。早晨跑到公司,吃完手里的早饭吃后,我们从源码库签出最新的源码,然后跑一下单元测试,发现有一些失败的测试,于是找相关的同事一起调试一下,修复了错误代码。接着回到自己的工作上来,编写自己的单元测试及产品代码,我们会感激IDE随时报出的编译错误提示,忙到午饭时间,代码编写得差不多了,测试也通过了,心满意足的吃饭休息。下午先昏昏沉沉得开了个例会,完了喝杯咖啡继续工作。刚才会上经理要求看测试报告,OK,找了相关工具集成进IDE,生成了像模像样的测试覆盖率报告,发了封电子邮件给经理,松了口气。同时看到QA那边又发过来了几个bug,没办法,先本地重现再说,于是熟练的点击IDE一些按钮生成了一个WAR包,部署到web容器下,启动容器。看到熟悉的界面了,遵循bug报告,一步步重现了bug……快下班的时候,bug修好了,提交代码,通知下QA,愉快的结束了一天的工作。 如果仔细总结下,我们会发现除了编写源代码,每天工作的相当一部分时间花在了编译,运行单元测试,生成文档,打包,部署等等繁琐且不起眼的工作上,这就是构建。我们往往觉察不到这部分时间的流逝,其实,只要稍微花点心思,这一系列的工作完全是可以自动化的。软件的构建可以像全自动流水线一样,只要一条简单的命令,所有繁琐的步骤都能够自动完成,我们很快就能得到最终的结果。 1.1.2 Maven是优秀的构建工具 前面介绍了Maven的用途之一是服务于构建,它是一个异常强大的构建工具,它帮我们自动化构建过程,从清理,编译,测试,到生成报告,到打包,部署。我们不需要,也不应该一遍又一遍的输入命令,一次又一次的点击鼠标。我们要做的是使用Maven配置好项目,然后输入简单的命令如mvn clean install,Maven会帮我们处理那些繁琐的任务。 Maven是跨平台的,这意味着无论你是在windows上,还是在Linux或者Mac上,你都可以使用同样的命令,构建同样的项目,得到同样的结果。 我们总是不停在寻找方法避免重复,设计的重复,编码的重复,文档的重复,当然还有构建的重复。Maven最大化的消除了构建的重复,它抽象了构建生命周期,并且为绝大部分的构建任务提供了已实现的插件,我们不再需要定义过程,我们甚至不需要再去实现这些过程中的一些任务。最简单的例子是测试,我们没必要告诉Maven去测试,我们更不需要告诉Maven如何运行测试,我们只需要遵循Maven的约定编写好测试用例,当我们运行构建的时候,这些测试便会自动运行。 想象一下,Maven抽象了一个完整的构建生命周期模型,这个模型吸取了大量其它构建脚本,构建工具的优点,总结了大量项目的实际需求。遵循这个模型,我们可以避免很多前人的错误,我们可以直接使用大量成熟的Maven插件来完成我们的任务(很多时候你可能都不知道你在使用Maven插件)。此外,如果你真得有非常特殊的需求,你也可以轻松实现自己的插件。 Maven还有一个优点是它能帮助我们标准化构建过程,在Maven之前,可能十个项目有十种构建的方式,现在,只要是使用了Maven,所有项目的构建命令都是简单一致的,这极大的减免了不必要的学习成本,并能帮助促进项目团队的标准化。 综上我们可以看到,Maven作为一个构建工具,它不仅仅能帮我们自动化构建,它还能够抽象构建过程,提供构建任务实现,它跨平台,并且对外提供了一致的操作接口,这一切足以使它成为优秀的,流行的构建工具。 1.1.3 Maven不仅仅是构建工具 很多人仅仅认识到Java是一门编程语言,但Java不只如此,它还是一个平台,通过JRuby和Jython,程序员们可以在Java平台上编写和运行Ruby和Python程序。 这里我也想提醒读者,Maven不仅仅是构建工具,它还是一个依赖管理工具,还是一个项目信息管理工具。它提供了中央仓库,并能帮你自动下载构件。 在这个开源的年代里,几乎任何一个Java应用都会借用一大堆第三方的开源类库,这些类库都通过依赖的方式引入到项目中来。随着依赖的增多,版本不一致,版本冲突,依赖臃肿等等问题都会显露出来。手工解决这些问题是一件枯燥乏味,确有不得不面对的事情。Maven提供了一个优秀的解决方案,它通过一个坐标系统准确定位每一个构件(Artifact),也就是用,通过一组坐标,Maven能够找到任何一个Java类库如jar文件,Maven给这个类库世界引入经纬,带来的秩序,于是我们就能借助它帮助我们有序的管理依赖,轻松的解决那些繁杂的依赖问题。 Maven还能帮助我们管理原本分散在项目各个角落的项目信息,包括项目描述,开发者列表,版本控制系统地址,许可证,缺陷管理系统地址,等等。这些微小的变化看起来很琐碎,并不起眼,但往往在不知不觉中节省了我们大量的寻找信息的时间。这些还只是直接的项目信息,通过Maven自动生成的站点和一些已有的插件,我们还能够轻松获得项目文档,测试报告,静态分析报告,源码版本日志报告,等等非常具有价值的项目信息。 Maven还给全世界的Java开发者提供了一个免费的中央仓库,在这里,我们可以找到几乎任何的流行开源类库,通过一些Maven的衍生工具如Nexus,我们还能对其进行快速得搜索。只要定位了坐标,Maven还能够帮我们自动下载。不再需要一个个的点击开源项目首页,不再需要寻找下载链接,不再需要手工的去下载。 1.2 为什么需要Maven Maven不是Java领域唯一的构建管理的解决方案。我们将通过一些简单的例子解释Maven的必要性,并介绍其它构建解决方案,如IDE, Make和Ant,并将它们与Maven作一些比较。 1.2.1 组装PC和品牌PC 我初中时候开始接触计算机,到了高中更是疯狂的想要一台自己的计算机,终于我得到了我的第一台计算机,它是赛扬733的。这是一个漫长的过程,我阅读了大量的杂志以了解各类配件的优劣,CPU,内存,主板,显卡,甚至是声卡,我都仔细挑选,后来还跑了很多商家,调货,讨价还价,组装好,接着自己装操作系统,驱动程序……我很享受这个过程,虽然这花费了我大量时间,而且事实证明最后装出来的机器稳定性也不怎样。 一年前我需要配一台工作站,这时候我已经没有太多时间去研究电脑配件了,我也变懒了。我选择了某知名PC供应商的在线商店,大概浏览了一下主流的选择,点击选择了我需要的配置,然后下单,付款。接着PC供应商会帮我组装电脑,安装操作系统和驱动程序,一周后,物流公司将我的电脑送到了家里,我简单地连接了显示器电源,就能直接使用了。这节省了我大量的时间,而且这台电脑十分稳定,我知道商家在把电脑发送给我之前已经进行了很好的测试。哦,对了,我还能享受两年的售后服务,虽然这是收费的。 使用脚本建立高度自定义的构建系统就像买组装PC,耗时费力,结果也不一定很好。当然,你可以享受从无到有的乐趣,但恐怕实际项目中没法给你那么多时间。使用Maven就像购买品牌PC,省时省力,并能得到成熟的构建系统,你还能得到来自于Maven社区的大量支持。唯一于购买品牌PC不同的是,Maven是开源的,你无须为此付费,如果需要,你还是能去了解Maven是如何工作的。而我可不知道那些PC巨头的商业秘密。 1.2.2 IDE不是万能的 当然,我们无法否认优秀的IDE帮助我们大大提高了开发效率。当前主流的IDE如Eclipse和NetBeans都提供了强大的文本编辑,调式,甚至重构功能。虽然使用简单的文本编辑器加上命令行也能完成几乎任何开发工作,但很少有人愿意那样做。然而IDE是有其天生缺陷的: IDE依赖大量的手工操作,编译,测试,或者代码生成,等等这些工作都是相互独立的,很难一键完成所有工作。而手工劳动往往就意味着低效,意味着容易出错。 很难在项目中统一所有的IDE配置,每个人都有自己的喜好。也正是由于这个原因,一个在机器A上可以成功运行的任务,到了机器B的IDE中,可能就会失败。 我们应该合理利用IDE,而不是过多的依赖它。对于构建这样的任务,在IDE中一次次点击鼠标是愚蠢的行为。Maven是这方面的专家,而且主流IDE如Eclipse和NetBeans都集成了Maven,这样,我们就可以在IDE中方便地运行Maven执行构建。 1.2.3 Make Make也许是最早的构建工具,它由Stuart Feldman于1977年在Bell实验室创建。他也因此于2003年获得了ACM国际计算机组织颁发的软件系统奖。目前Make有很多衍生实现,包括最流行的GNU make,以及BSD Make,还有Windows平台的Microsoft nmake等等。 Make由一个名为Makefile的脚本文件驱动,该文件使用Make自己定义的语法格式,其基本组成部分为一系列规则(Rules),而每一条规则的构成部分又包括:目标(Target),依赖(Prerequisite),和命令(Command)。Makefile基本的结构如下: Make通过一系列目标和依赖将整个构建过程串联起来,同时利用本地命令完成每个目标的实际行为。Make的强大之处在于它可以利用一切系统的本地命令,尤其是对于Unix/Linux系统来说,丰富的功能强大的命令能够帮助Make快速高效的完成任务。 但是,Make将自己和操作系统绑定在一起了,也就是说,使用Make,你就不能实现(至少很难)跨平台的构建。这对于Java来说是非常不友好的。此外,Makefile的语法也成问题,很多人抱怨他们Make构建失败的原因往往是一个难以发现的空格或Tab使用错误。 1.2.4 Ant Ant不是指蚂蚁(英文中Ant是蚂蚁的意思),它意指“另一个整洁的工具(Another Neat Tool)”,它最早用来构建著名的Tomcat。其作者James Duncan Davidson创作该工具的动机就是因为受不了Makefile的语法格式。我们可以将Ant看成是一个Java版本的Make,也正是使用了Java,Ant是跨平台的;此外,Ant使用XML定义构建脚本,这相对于Makefile来说也更加的友好。 与Make类似,Ant有一个构建脚本build.xml,如下: Build.xml的基本结构也是目标(target),依赖(depends),以及实现目标的任务。比如上面的脚本中,jar目标用来创建应用程序jar文件,该目标依赖于compile目标,后者执行的任务是创建一个名为classes的文件夹,编译当前目录的java文件至classes目录。Compile目标完成后,jar目标再执行自己的任务。Ant有大量内置的java实现的任务,这保证了其跨平台的特质,同时,Ant也有特殊的任务exec来执行本地命令。 和Make一样,Ant也都是过程式的,开发者显式的指定每一个目标,及完成该目标所需要执行的任务。针对每一个项目,开发者都需要重新编写这一过程,这里其实隐含着很大的重复。而Maven是声明式的,项目构建过程以及过程各个阶段所需的工作都由插件实现,并?xml version=1.0? project name=Hello default=compile target name=compile description=compile the Java source code to class files mkdir dir=classes/ javac srcdir=. destdir=classes/