背景
在使用Eclipse进行项目合作开发的时,我们是如何进行项目依赖管理的呢?
我们通常会在新建项目的时候,同时建立一个lib目录,在其中放着项目所依赖的各方类库,这样提交到SVN之后, 每个开发人员检出项目到本地,得到项目的工作副本,这样所有开发人员就会持有统一的项目依赖了。
【1】依赖冗余,浪费空间:但是,随着项目的增多,模块的增多,这种方式就会有问题。很多模块都会引用相同的依赖,当每个模块都把自己的依赖提交到SVN,那么相同的依赖就会占用服务器SVN的Repository很大的空间,造成空间浪费。
【2】版本问题:同时,如果一个项目中依赖的版本和另一个项目依赖的版本不一致。比如这个项目依赖hibernate2.x,而另一个可能依赖hibernate3.x, 当合并两个项目发布的时候, 可能因为这种依赖类库详细版本信息的缺失,造成问题。
是什么
为了解决以上依赖管理过程中出现的问题, 我们寻求出一种集中式的依赖管理方式。各个项目只要通过统一的依赖描述文件(pom.xml)来指定自己需要的依赖就可以, 而不用自己来管理真正的依赖库,因为所有的项目都使用同一个*依赖库(*仓库), 所以即使各个项目中有相同的依赖, 也不会出现依赖冗余的问题。
Maven是基于POM的一款进行项目依赖管理,构建管理和项目信息管理的工具。
优点
【1】“约定优于配置(Convention over Configuration)”,maven提供了约定的项目的目录结构,自动创建项目目录,提高开发效率。
目录结构:
main :源代码
test : 放测试类
resource:资源文件src
–main
—-java
——package
–test
—-java
——package用命令自动创建目录的两种方式:如:mvn archetype:generate
【2】简单的构建过程:编译、清理、测试、打包、部署等。通过输入简单的命令就可以完成这些工作。
compile:编译
test:测试
package:打包
clean :清理target文件,删除maven生成的目标文件,target中存放的是编译后的class文件和测试报告
install:安装jar包到本地仓库中
Maven编译项目流程
最原始的java程序运行:
Java 程序是由若干个 .class 文件组成的。这些 .class 文件必须根据它们所属的包不同而分级分目录存放;运行前需要把所有用到的包的根目录指定给 CLASSPATH 环境变量或者通过 java 命令的 -cp 参数;运行时还要到控制台下去使用 java 命令来运行。
使用maven编译项目的流程:
1.执行mvn compile 编译源代码
2.如果用到其他jar包时会去pom.xml中的找坐标
3.根据坐标去本地仓库中查找:
如果有,则将jar包加入到classpath中
如果没有,会去maven的*仓库找,下载放到本地仓库中,再加入到classpath中。
基本概念
仓库:管理和存放项目依赖
坐标:项目依赖的唯一标示
生命周期:
clean :清理项目 clean
default:构建项目 compile test package install
site:生成项目站点
【备注】:如果执行mvn package命令,会先自动执行compile 和test命令。
依赖范围:
有三种classpath(编译,测试,运行),规定依赖范围就是控制依赖与classpath的关系, 不同的范围,就会寻找不同classpath下的jar包进行执行。
♥compile 【默认方式】:编译,测试,运行,打包的时候都会加入依赖(默认方式)
♥provided:编译和测试的时候会加入依赖,运行时不会,打包时不会。如:项目依赖Servlet API,但是运行时不依赖。因为Web Container中已经有,这样避免了冲突 。
♥runtime:在运行和测试的时候依赖,在编译的时候不依赖
♥test:测试时依赖,编译和打包时不依赖,测试时才有用的依赖。如:要把(如Junit)scope设置成test。
♥system:和provided一样 编译和测试时候有效,与本机系统相关联,可移植性差
♥import:导入的范围,表示如将项目B中的依赖导入到A当中,只是用在dependencyManagement中
依赖:
传递依赖:A–>B–>C,项目A对项目C是间接依赖,此时项目A中就会有项目C的jar包,可以通过exclution标签排除jar包。
依赖冲突:
1.短路优先:A–>B–>C–>X(V1.0)同时A–>D–>X(V2.0),那么A会依赖V2.0的X。
2.先声明优先:A–>B–>X(V1.0),A–>C–>X(V2.0),那么看在A的pom的xml文件中,先声明的是B的依赖还是C的依赖,A会依赖先声明者所依赖的该版本的X。
聚合:需要将多个项目同时安装时,可以通过module进行配置
继承:多个项目中含有共同的依赖,将这些依赖抽到父类中,用dependencyManagement标签进行管理,子类中通过parent标签进行继承。
总结
所谓构建就是包括编译,运行单元测试,生成测试报告(还记得target文件夹吗?那里存放着测试报告),打包,部署等一系列过程。我们通过Maven可以方便地自动化的完成这些,仅仅是通过一个mvn clean install命令。虽然我最初用它时,以为它仅仅是一个管理项目依赖的工具,类似于NuGet(.NET平台下的免费、开源的包管理开发工具)。现在看来它的功能还有待我去实践和发掘。有兴趣地可以阅读一下《Maven实战》这本书。