(五)Maven仓库
Maven仓库
在Maven世界中,任何一个依赖、插件或者项目构建的输出,都可以成为构件(jar、war包等)。
Maven在某个位置上统一存储所有Maven项目共享的构件,即为Maven仓库;Maven项目不用各自存储依赖文件,只需声明依赖的坐标,在需要时(编译、运行、打包),Maven会自动根据坐标找到Maven仓库中的构件,并使用它们。仓库的布局
在Maven世界中,任何一个构件都有其唯一的坐标,通过坐标可以定义其在仓库中的唯一存储路径,即Maven的仓库布局方式。
Maven构件的存储路径为:groupId/artifactId/version/artifactId-version[-classifier].packagingPs(个人理解): 仓库的布局方式就是定义了坐标与构件路径的对应关系,即如何通过坐标找到构件。仓库的分类
对Maven而言,仓库只分为两类,本地仓库、远程仓库。而远程仓库又可细分为中央仓库、私服、其他公共库。
当Maven根据坐标寻找构件时,首先查看本地仓库,如果不存在,Maven就会去远程仓库查找并下载到本地文件。如果都没有,Maven就会报错。分类如下图1 本地仓库
通常Maven项目目录下,没有诸如lib/这样存放依赖文件的目录,Maven总是基于坐标使用本地仓库的依赖文件。
默认情况下,不论是Windows还是Linux,本地仓库的路径都为~/.m2/repository(~ 是用户目录)更改本地仓库路径:~/.m2/settings.xml,设置localRepository元素的值。如:... D:\java\repository ...
安装构件到本地仓库:
1)mvn clean install:构建项目输出文件并安装到本地仓库2)mvn install:install-file -Dfile=x -DgroupId=x -DartifactId=x -Dversion=x -Dpackaging=xDfile待安装构建路径;DgroupId、DartifactId、Dversion、Dpackaging声明其在仓库中的坐标2 远程仓库
安装好Maven后,如果不执行任何Maven命令,本地仓库目录是不存在的。当用户输入第一条Maven命令之后,Maven才会创建本地仓库,然后根据配置和需要,从远程仓库下载构件至本地仓库。
Maven本地仓库只有一个,但可以配置多个远程仓库。好比本地仓库是书房,远程仓库是书店,当用户需要看一本书时,如果在书房中没找到,就到书店购买并放回书房。通常一个人只有一个书房,但外面的书店有很多。3 中央仓库
由于原始的本地仓库是空,Maven必须知道至少一个可用的远程仓库,才能在执行Maven命令时下载到需要的构件。
中央仓库就是这样一个默认远程仓库。在Maven安装文件中自带了中央仓库的配置。在Maven安装目录/lib/maven-model-builder-xx.jar中访问路径org/apache/maven/model/pom-4.0.0.xml。Ps(个人理解):pom-4.0.0.xml 与 pom.xml中<modelVersion>4.0.0</modelVersion> 应该存在某些关联pom-4.0.0.xml是所有Maven项目都会继承的超级POM,查看该文件,可以找到中央仓库配置。central Central Repository https://repo.maven.apache.org/maven2 default false
4 私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务。私服代理广域网上的远程仓库,供局域网内的Maven用户使用。
上图展示了组织内部使用私服的情况,即使在一台直接连入Internet的个人机器上使用Maven,也应本地建立私服。
建立私服的优点:节省自己的外网带宽 | 消除对外的重复构件下载,降低外网带宽的压力。 |
加速Maven构建 | 不停的请求外部仓库十分耗时,Maven的一些内部机制(如快照更新检查)要求Maven在执行构建时不停地检查远程仓库数据,当项目配置很多外部远程仓库时,构建速度大大降低。使用私服,Maven只需检查局域网内私服数据,提高构建速度。 |
部署第三方构建 | 安装组织内部生成的私有构件到私服,供内部Maven用户 |
提高稳定性,增强控制 | Maven构建高度依赖于远程仓库,Internet不稳定,Maven构建也会变得不稳定,甚至失败,使用私服后,即使暂时没有Internet,由于私服缓存了很多构件,Maven也能正常运行。此外,很多私服(如Nexus)软件还提供了额外的功能,如权限管理,RELEASE/SNAPSHOT区分等 |
降低中央仓库的负荷 | 使用私服可以避免很多对中央仓库的重复下载。 |
远程仓库的配置
在POM中配置远程仓库
... ... ... ... ... ... ... ... ... ... default
1 远程仓库的认证
大部分远程仓库无须认证就可访问,但有时出于安全方面考虑,我们需要提供认证信息才能访问一些远程仓库。
配置认证信息必须配置在settings.xml中,因为POM往往提交到代码仓库中供所有成员访问,显然,本地settings.xml更安全... ... .. ... ...
2 部署至远程仓库
1) 编辑项目的pom.xml
... ... ... ... ... ...
2) 往远程仓库部署构件时,往往需要认证。在settings.xml中配置认证信息
3)执行mvn clean deploy,部署到远程仓库快照版本
在Maven世界中。任何一个项目或者构件都必须有自己的版本,而Maven又将版本分为两种:
发布版本:稳定,格式如:1.0.0、1.3-alpha-4、2.0快照版本:不稳定,格式如:2.1-SNAPSHOT、2.1-20091214.221414-13假设:同时开发项目A、B,而项目B依赖于项目A,在项目未正式方布时,开发方案如下
方案一:检出项目A源码进行构建。能获得项目A最新构件,但需要额外的构建操作,而且构建出问题也不好解决,低效方案二:重复部署项目A,版本号不变。需要清理本地仓库相同版本号的项目A构件,不然无法下载A最新构件方案三:不停更新版本。需要频繁修改POM文件,同时造成版本号的滥用。方案四:将项目A的版本设置为快照版本。Maven在发布项目快照版本时,会自动打上时间戳。如2.1-20091214.221414-13 表示 2009年12月14日22时14分14秒 第13次快照。通过时间戳,Maven就能找到该构件的最新快照版本。
默认情况下,Maven会每天检查一次更新(由仓库配置的updatePolicy控制),也可通过-U命令强制更新,如mvn clean install -U从仓库解析依赖的机制
当本地仓库没有依赖构件时,Maven会自动从远程仓库下载;当依赖版本为快照版本时,Maven会自动找到最新的快照。其依赖解析机制如下
1)依赖范围是system,Maven直接从本地文件系统解析构件。2)根据依赖坐标计算仓库路径,Maven直接从本地仓库寻找构件,如果发现相应构件,则解析成功。3)本地仓库不存在,且依赖版本是显式的发布版本构件(1.0,1.2-beta-1),遍历所有远程仓库,发现后下载并解析使用4)如果依赖版本是RELEASE和LATEST,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/maven-metadata.xml,将其与本地仓库的对应元数据合并后,计算出RELEASE或LATEST的真实的值,然后基于这个值检查本地和远程仓库。5)如果依赖版本是SNAPSHOT,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/version/maven-metadata.xml,将其与本地仓库的对应元数据合并后,得到最新快照版本的值,然后基于该值检查本地仓库和远程仓库。6)如果最后解析得到的构件版本是时间戳格式的快照,如1.4.1-20091104.121450-121,则复制其时间戳格式文件至非时间戳格式,如SNAPSHOT,并使用该非时间戳格式的构件。Maven基于更新策略来检查更新,与远程仓库配置中<release>和<snapshot>中的子元素<enable>、<updatePolicy>有关,只有enable为true,才能访问该仓库对应发布版本/快照版本的构件信息,并基于updatePolicy更新策略检查更新,使用-U可以强制更新。
当Maven检查完更新策略,并决定检查依赖版本,就需要检查仓库元数据maven-metadata.xml基于groupId和artifactId的maven-metadata.xmlorg.sonatype.nexus nexus 1.4.2-SNAPSHOT 1.4.0 1.3.5 1.3.6 1.4.0-SNAPSHOT 1.4.0.1-SNAPSHOT 1.4.1-SNAPSHOT 1.4.2-SNAPSHOT 20091214221557
该XML文件列出仓库中存在的该构件的所有可用的版本,Maven通过合并多个远程仓库及本地仓库的元数据,就能计算出基于所有仓库的latest和release分别是什么,然后再解析具体的构件。
Ps:不推荐依赖声明中使用LATEST和RELEASE,Maven随机解析到不同的构件,当构件发生变化,可能会造成项目构建失败,且不易排查。当依赖版本是快照版本时,Maven也需要检查更新。
基于groupId、artifactId和version的maven-metadata.xmlorg.sonatype.nexus nexus 1.4.2-SNAPSHOT 20091214.221414 13 20091214221414
该XML文件的snapshot元素包含timestamp和buildNumber两个元素分别代表这一快照的时间戳和构建号。并由此可以得到该仓库中此快照的最新构件版本实际为1.4.2-20091214.221414-13,通过合并所有远程仓库和本地仓库的元数据,就能知道所有仓库中该构件的最新快照。
最后,元数据并非永远正确,当某些构件无法解析,或解析错误时,需手工或使用工具(如Nexus)对齐进行修复。
镜像
如果仓库X可以提供仓库Y存储的所有内容,那么就可以认定X是Y的一个镜像。
举个例子,://repol.maven.org/maven2在中国的镜像,由于地理位置因素,使用该镜像往往能够提供比中央仓库更快的服务。编辑settings.xml,配置镜像
... ... ... ... ... ...
mirrorOf元素用来匹配被镜像仓库(有点类似于Servlet的url-pattern表达式),当你要访问的远程仓库id满足mirrorOf表示式时,就会被拦截访问镜像服务器。表达式语法如下:
* | 匹配所有远程仓库 |
external:* | 匹配所有远程仓库,localhost除外 |
a,b | 匹配a和b仓库,多个仓库用,隔开 |
*,!a | 匹配所有远程仓库,a除外,使用感叹号将仓库从匹配中排除 |
仓库搜索服务
使用Maven进行日常开发时,获取依赖需要确切的依赖坐标,通过仓库搜索服务可以根据关键字得到Maven坐标。
Sonatype Nexus | 提供关键字搜索、类名搜索、坐标搜索、校验和搜索等功能,坐标和构件下载 | |
aliyun Nexus | 同上,aliyun架设的公共Nexus仓库实例,服务较快 | |
Jarvana | 提供基于关键字、类型搜索,坐标,构件下载。还支持浏览构件内部内容和便捷的Java文档浏览功能 | |
MVNbrowser | 只提供关键字搜索,坐标,还可查看构件依赖于那些构件(Dependencies)以及该构件被哪些其他构件依赖(Referenced By) | |
MVNrepository | 提供关键字搜索,坐标,构件下载,依赖于被依赖关系信息,构件所含信息,还能提供一个简单图表,显示某个构件各版本间的大小变化 |