Maven 出现到现在也有很长时间了,初识它的感觉至今仍清晰的印在脑海中。现在想来,当时从 Ant 移情 Maven 的想法其实很朴素,就是因为 Maven 可以以网站的形式展现与项目相关的信息,如开发人员列表、各种 Report。这种方式为项目的构建带来了极大的方便,尤其是 Report 的。试想对于产生的 Junit-Report、JavaDoc、CheckStyle、PMD 等报告,如果没有一个统一的入口,每次切换目录是多么令人厌烦的事情!
Maven 无疑是相当成功的,这一点从越来越多的开源项目开始使用 Maven 就可以看出。Maven 取得成功的原因很简单:在简化构建脚本的同时,功能并没有缩水,反而有所增强;提供汇集项目信息的工具,并以相当友好的方式呈现;丰富的插件简化了工作。 如此有力的工具出现,自然是争相使用。
如今 Maven2 已经推出,Maven 的官方网站称,Maven2 相对于 Maven1 是一个相当大的转变,甚至不惜牺牲兼容性来达到这一目的。(为了 Maven1 的用户着想,Maven1 仍在继续他的使命。)如此大的变动到底换来了什么样的结果?
比起 Maven1 那不急不慢的运行速度,Maven2在速度上有了质的飞跃,甚至与Ant相比也毫不逊色(当然,下载不算)。除此之外,"简化工作,使用业界公认的最佳实 践"也是是 Maven2 的另一大主题,其他的新特性无处不在体现 Maven2 为简化工作而做出的努力。
Maven1 和 Maven2 主要配置文件的对比:
POM是Maven的核心对象模型,在Maven2中POM已由project.xml转移到pom.xml中使用,版本也由3升级为4。对于项目,一般只需要pom.xml就行了。
在Maven2中不需要也不提倡使用maven.xml,原因如下:
如果仍期望能够使用类似maven.xml的功能,如<preGoal>,请参考Inserting non-standard build steps using preGoals and postGoals。
在Maven2中,配置使用settings.xml,它取代了原有的project.properties和build.properties。配置在Maven2中存在两种级别:
在settings.xml中可以配置,如本地Repository、proxy等等,关于settings.xml的结构可以从Maven的官方网站上获取。
在Maven2中,编写plugin的语言由jelly变更为Java和BeanShell。Java在速度上更有优势,而且开发人员的熟悉程度更高。对于其他的流行脚本,如groovy,Maven的官方网站的意见是,等待其更成熟时再考虑
。好的目录结构可以使开发人员更容易理解项目,为以后的维护工作也打下良好的基础。Maven2根据业界公认的最佳目录结构,为开发者提供了缺省的标准目录模板。Maven2的标准目录结构如下:
使用目录模板,可以使pom.xml更简洁。因为Maven2已经根据缺省目录,预定义了相关的动作,而无需人工的干预。以resources目录为例:
这些动作在 Maven1 中,是需要在 maven.xml 中使用<preGoal>或<postGoal>来完成的。如今,完全不需要在pom.xml中指定就能够自动完成。在src和 test都使用resources,方便构建和测试,这种方式本就已是前人的经验。通过使用Maven2,使这个经验在开发团队中得到普及。
创建标准目录模板,可以通过如下命令:
mvn archetype:create -DgroupId=com.codeline.commons -DartifactId=codelineCommons |
groupId和artifactId的含义与Maven1中的含义一样,参数artifactId的值会作为项目根目录的名字。除了建立相应的目录之外,Maven2还会创建缺省的pom.xml。
Maven2也考虑到:不同类型的项目需要拥有不同的目录结构。如创建web项目,可以使用命令:
mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp |
在Maven2中有了明确的生命周期概念,而且都提供与之对应的命令,使得项目构建更加清晰明了。主要的生命周期阶段:
如果要执行项目编译,那么直接输入:mvn compile即可,对于其他的阶段可以类推。阶段之间是存在依赖关系(dependency)的,如test依赖test-compile。在执行 mvn test时,会先运行mvn test-compile,然后才是mvn test。
在POM 4中,<dependency>中还引入了<scope>,它主要管理依赖的部署。目前<scope>可以使用5个值:
<scope>的使用举例:
<dependency> <groupId>hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.0.3</version> <scope>test</scope> </dependency> |
在Maven1中,需要把依赖所需要的包也一并列出。这对于使用类似如Hibernate的用户来说所操的心太多了,而且也不方便。在Maven2 中实现了传递依赖,如此对于Hibernate所依赖的包,Maven2会自动下载,开发人员只需关心Hibernate即可。
注意:只有得到Maven支持的依赖,通常是plugin形式出现,才能获得这个特性。而且对于一些老的plugin,可能由于时间的关系不支持传 递依赖。如至少在Maven 2.0.1中,对于Hibernate 2.1.2,仍然需要显式列出Hibernate 2.1.2所依赖的包。