Maven学习札记(二) 坐标、依赖、仓库

Maven学习笔记(二) 坐标、依赖、仓库
今天学习了Maven中坐标、依赖和仓库三个比较重要的概念。

坐标(Coordinate):
Maven定义的规则,用于唯一标识一个构件。包括groupId,artifactId,version,packaging和classifier。

解释如下:
groupId: 定义当前Maven项目所隶属的实际项目,如org.sonatype.nexus,这是一个大项目的概念。
artifactId: 定义实际项目中的一个Maven项目,或者说是模块,推荐用实际项目名作为artifactId的前缀,如nexus-core。
version: 定义Maven项目当前所处的版本号,Maven在其中定义了一套完整的版本规范。如SNAPSHOT等。
packaging: 定义Maven项目的打包方式,默认为jar,通常会与最终生成的构件的扩展名对应。
classifier: 定义构件输出的一些附属构件。如javadoc,sources等,他们也拥有自己唯一的坐标。值得注意的,不可以直接定义项目的classifier,因为这不

是项目直接默认生成的,而是由附件的插件帮助生成。

当然之后学到的仓库的布局也是基于Maven坐标的。


依赖(Dependency):

pom.xml配置文件根元素project下的dependencies可以包含若干个Dependency元素,以声明项目依赖。而依赖又可包含groupId,artifactId,version三个基本

坐标元素和type,scope,optional,exclusions等元素。

解释如下:
type: 依赖的类型,其实是与坐标中packaging相对应的,默认jar。
scope: 声明依赖的范围,有compile,test,provided,runtime,system几种,稍候详述。
optional: 用于标记依赖是否可选。
exclusions:用于排除依赖传递性,稍候详述。


依赖范围scope: 用来控制依赖于classpath(包括编译、测试、运行三种classpath)的关系。
compile: 默认的依赖范围,对于三种classpath均有效,如spring-core。
test: 只对测试classpath有效,如JUnit。
provided: 对于编译和测试classpath有效,因为一般在运行时环境以提供,如servlet-api。
runtime: 对于测试和运行classpath有效,如JDBC驱动实现。
system: 对于编译和测试classpath有效,但必须通过SystemPath元素显式指定依赖文件的路径,往往与本机系统绑定,可移植性差,慎用。


依赖传递性:避免下载过多不必要的jar包或缺失某些包。Maven会逐层解析各个直接依赖的POM,把必要的间接依赖引入当前项目。

依赖调节:当依赖关系出现不同路径的冲突时,如A->B->C->X(1.0),A->D->X(2.0),Maven根据两个原则进行选择:1、路径短者优先 2、第一声明者优先。

最佳实践:
1、排除依赖:exclusion元素,排除掉或者手工替换某个传递性依赖,以保证稳定性。
2、归类依赖:properties元素定义类似版本号springframwork.version的元素,类似于常量,用${}在后续配置文件中引用,便于统一管理和修改。
3、优化依赖:Maven自动解析所有项目的直接依赖和传递性依赖,并按规则调整一些冲突,保证任何构件只有唯一的版本存在。可用命令mvn dependency:list或

mvn dependency:tree查看当前项目的已解析依赖。


仓库(Repository):

根据我的理解,Maven的仓库其实替代了以前编程中用的lib目录。只不过以前的不同项目lib目录下会有大量的重复而且每次都要手动添加。难以统一管理,也浪

费磁盘空间。而Maven仓库得益于坐标机制,只要在某处统一存储所有Maven项目共享的构件,任何实际项目中只要声明依赖的坐标,Maven便可在需要的时候自动

找到并使用它们。而为了便于重用,项目构建完毕后生成的构件仍可安装或部署到仓库*后续项目使用。

仓库的布局方式其实简洁明了,基本上与坐标的对应关系是:grouptId/artifactId/version/artifactId-version.packaging。

Maven仓库大体上分为两类:本地和远程。

本地仓库默认在用户目录.m2/repository下,通过这两天的实践,我的本地仓库下也有了不少Maven下载的构件了。这些已经存在的构件在以后的项目中如有需要

就可以直接根据坐标找到来使用而无需重新下载。

远程仓库主要包括了*仓库,服务器和其他公共库。
其中*仓库包含了绝大多数流行的开源构件,便是Maven“开箱即用”理念的核心体现。
服务器则往往应用于局域网内,代理广域网上的远程仓库,共内部用户使用。好处主要在于节省带宽、加速构建、部署第三方构件(有些由于版权问题无法从外部

仓库获得的以及内部自行开发的构件)等等。目前最流行的服务器软件是Nexus。名字跟谷歌儿子似的。。。

最后简单提一下快照版本。Maven要求任何项目或构件都有自己的版本号。Maven主要区分了发布版和快照版。版本设定为SNAPSHOT的构件在发布的过程中,Maven

会自动打上时间戳,便于随时找到仓库中该构件的最新文件。快照版本一般应用于内部项目和模块间依赖,因为这往往是不稳定的。因此正式发布的时候应该将版本号改为发布版alpha。