前言
相信只要做过 Java 开发的童鞋们,对 Ant 想必都不陌生,我们往往使用 Ant 来构建项目,尤其是涉及到特别繁杂的工作量,一个 build.xml 能够完成编译、测试、打包、部署等很多任务,这在很大的程度上解放了程序员们的双手。但同时也存在一些其他的问题,比如:jar 文件管理混乱,每次都需要自己去下载;build.xml 因项目结构的不同导致差异性较大。
概况
自从项目中引入 Maven 以后,以前 Ant 能解决的,Maven 提供了更加简洁的解决方案,而以前 Ant 解决不了的,Maven 也能很好的解决。这就直接导致了项目管理工具的更新换代。当然,这已不是什么新鲜事了。只不过,一直到现在才有时间来分享项目中使用 Maven 的感受,这一点上,真的很抱歉,后续会及时的更新。
Maven 的入门教程网上已经有很多了,这里就不再赘述这些基本知识了。还没有接触过 Maven 的童鞋,请移步 Google 或 Baidu。之后再回来看这篇文章。在这篇文章里,我主要结合项目中 Maven 的使用,以及需要注意的事项来与大家讨论。
原理
说到 Maven 的原理,其实很简单,就是采用远程仓库和本地仓库以及一个类似 build.xml 的 pom.xml,将 pom.xml 中定义的 jar 文件从远程仓库下载到本地仓库,各个应用使用同一个本地仓库的 jar,同一个版本的 jar 只需下载一次,而且避免每个应用都去拷贝 jar。
同时它采用了现在流行的插件体系架构,只保留最小的核心,其余功能都通过插件的形式提供,所以 Maven 下载很小(1.1M),在执行 Maven 任务时,才会自动下载需要的插件。而且,Maven 还是跨平台的,并且提供了支持很多 Java IDE 的扩展插件。在开发中,我们大部分的时间,用到的是 Maven 的插件。对于公司内部来说,还是需要建立自己的私服的,不过,这里私服不是重点,就不再讨论了。
结构
项目中我们都会根据自己的习惯创建目录结构,虽然有规范,但难免会有疏漏,长此下去,项目的结构会越来越乱的。Maven 解决了这个问题,对于不同的项目,它提供了多种选择,并将其作为目录模板,如下图所示。
使用目录模板,可以使pom.xml更简洁。因为Maven2已经根据缺省目录,预定义了相关的动作,而无需人工的干预。以resources目录为例:
- src/main/resources,负责管理项目主体的资源。在使用Maven2执行compile之后,这个目录中的所有文件及子目录,会复制到target/classes目录中,为以后的打包提供了方便。
- src/test/resources,负责管理项目测试的资源。在使用Maven2执行test-compile之后,这个目录中的所有文件及子目录,会复制到target/test-classes目录中,为后续的测试做好了准备。
这些动作在 Maven1 中,是需要在 maven.xml 中使用<preGoal>或<postGoal>来完成的。如今,完全不需要在pom.xml中指定就能够自动完成。在src和test都使用resources,方便构建和测试,这种方式本就已是前人的经验。通过使用Maven2,使这个经验在开发团队中得到普及。
生命周期
在 Maven2 中有了明确的生命周期概念,而且都提供与之对应的命令,使得项目构建更加清晰明了。主要的生命周期阶段:
- validate,验证工程是否正确,所有需要的资源是否可用。
- verify,运行任何检查,验证包是否有效且达到质量标准。
- integration-test,在集成测试可以运行的环境中处理和发布包。
- generate-sources,产生应用需要的任何额外的源代码,如xdoclet。
- compile,编译项目的源代码。
- test-compile,编译项目测试代码。
- test,使用已编译的测试代码,测试已编译的源代码。
- package,已发布的格式,如jar,将已编译的源代码打包。
- install,把包安装在本地的repository中,可以被其他工程作为依赖来使用。
- deploy,在整合或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。
如果要执行项目编译,那么直接输入:mvn compile即可,对于其他的阶段可以类推。阶段之间是存在依赖关系(dependency)的,如test依赖test-compile。在执行mvn test时,会先运行mvn test-compile,然后才是mvn test。当然,开发中,我们一般都不会直接操作 Maven 的。而是在 Eclipse 中使用 Maven 插件,其中用的最多的命令就是 clean 、compile 、install 、deploy 等。
依赖
说完生命周期,还有一个必须要说的就是依赖管理了。Maven 中是通过在 pom.xml 中添加依赖从而来引入 jar 包的。其原理是:每一个 jar 都会有独立的坐标,Maven 就是通过坐标来定位到具体的 jar 的。
就好像平面坐标系一样,通过 x 轴 和 y 轴定位一个坐标点。Maven 定义了这样一组规则:世界上任何一个构件都可以使用 Maven 坐标唯一标识,Maven 坐标的元素包括 groupId 、artifactId 、version 、packaging 、classifier 。只要我们提供正确的坐标元素,Maven 就能够找到它。
建议
有的人可能会有疑问,以前没有 Maven 的时候,我们可以去各自的官网下载 jar,但现在只能通过 pom 引用 jar。那么如何知道需要添加哪些依赖呢?还有需要什么版本呢?这也是为什么有一部分习惯了自己下载 jar,而到了 Maven 这不知道该怎么用了。
当然,Maven 还不是智能的,你不可能直接命令 Maven 直接给你找项目所需要的各种组件,或许以后这样的智能化的软件管理工具会出现,至少现在还没有。因此,还得需要你自己去添加 pom 依赖。至于该如何找,这里我告诉大家一个方法,虽然方法有点笨,但或许对你快速定位到具体组件有所帮助。
举个例子,假如现在需要添加 Hibernate 的依赖,但具体哪个版本呢,可以先不用管,直接去 Baidu 或者 Google,以“ maven spring repository ”为关键字搜索,往往第一个链接中,就是你需要的方案。
进入第一链接之后,你会看到这样一个页面,搜索的结果都是关于 Spring 的,根据你的需要,选择一个链接进入,列表中有各个版本的组件,点击你需要的版本,然后就会看到 Maven 坐标。把它复制到你的 pom 文件中就噢啦。
当然,这只是一种方法,只针对刚接触 Maven 的童鞋们。随着项目经验的增多,以后你就会越来越发现,Maven 解放的不仅仅是你的双手,还有你最宝贵的时间。
感受
在一个项目中选择使用一款管理工具是有风险的,那么该如何把这种风险减到最低,或者让它转变为对项目开发有利的一方面呢?这就需要架构师或者项目组长,在项目开始之前进行严格的技术考察、技术(工具)选型、学习成本的分析等。
选择一种技术或者一款工具,不能仅仅因为它的流行程度,还要考虑到本公司开发人员的技术程度,技术(工具)的跨平台性考虑,扩展性与集成性的考虑,以及技术(工具)稳定性的考虑等。当然,对于一种新技术(对开发人员来说是新技术),还需要考虑学习成本,这些都制约日后的开发效率、开发进度,以及出问题后能不能解决等。
所谓的技术选型,并不是选出多么新的技术,也并不是选出成本最低的技术,而是能够利用本公司的优势,找出最适合本公司的技术和工具,在有限的范围内、有限的时间内把本公司的能力发挥到最大。
就比如,如果在项目管理工具上,公司里一直都在用 Ant,而且用的也特别的熟练,况且项目的时间特别紧急,公司的开发人员对 Maven 都没有接触过,那么就不用再考虑 Maven 了,因为时间在那摆着呢,而且还有开发人员的学习成本,这种情况下再选择 Maven,这不是 zuo si 吗?当然,这种例子不胜枚举,这里就不再多说了。
结束语
本来应该在最后说的话,都放在了感受里边,对于项目管理,还有很多欠缺的,希望在日后的工作中继续积累经验吧。当然,也希望大家能够多交流,共同进步。