Maven仓库

坐标依赖是任何一个构件在Maven世界中的逻辑表示方式任何一个构件都有一组坐标唯一标识,而构件的物理表示方式是文件,Maven通过仓库来统一管理这些文件

仓库布局

任何一个构件都有其唯一的坐标根据这个坐标可以定义其在仓库中的唯一存储路径,且存储路径大致对应关系为groupId/artifactId/version/artifactId-version[-classifier].packaging这便是Maven的仓库布局

Maven仓库是基于简单的文件系统存储的,当遇到一些仓库问题时,能很方便地查找相关文件,方便问题定位。

仓库分类

仓库只分为本地仓库远程仓库两类。Maven根据坐标寻找构件时,先查看本地仓库,若存在直接使用;若不存在或需要查看是否有更新的构件版本,再去远程仓库查找,发现后下载到本地仓库再使用。若本地仓库和远程仓库都没有Maven就会报错

中央远程仓库是Maven核心的自带的远程仓库,其包含了绝大部分开源构件。默认使用中央仓库

私服是另一种特殊的远程仓库,为了节省带宽和时间,应在局域网内架设一个私有的仓库服务器,使其代理所有外部远程仓库,且内部项目还能部署到私服上供其他项目使用。

除中央仓库和私服外还有很多其他公开的远程仓库,Java.net Maven库JBoss Maven库

Maven仓库分类

中央仓库

Maven安装文件自带中央仓库的配置,在$M2_HOME/lib/maven-model-builder-3.3.9.jar/org/apache/maven/pom-4.0.0.xml中,且这段配置的文件是所有Maven项目都会继承的超级POM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<!-- 不从中央仓库下载快照版本的构件 -->
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<!-- 不从中央仓库下载快照版本的构件 -->
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>

私服

私服代理广域网上的远程仓库,下载构件时从私服请求,若不存在则从外部远程仓库下载,缓存到私服后再提供下载服务,一些无法从外部下载的构件也能从本地上传到私服共大家使用。

Maven私服用途

降低中央仓库负荷

节省外网带宽:私服能消除大量对外部仓库的重复请求,从而节省带宽

加速Maven构件:Maven快照更新检查等机制要求在执行构件时不停检查远程仓库数据,若配置了很多外部远程仓库,由于不停的连接请求外部远程仓库非常耗时,导致构件速度大大降低,使用私服只需要检查局域网私服的数据

部署第三方构件:如一些组织内部私有构件无法从外部仓库获取,但又不能发布到公共仓库,可以发布到私服中,供内部的Maven项目使用

提高稳定性增强控制:Maven构建高度依赖远程仓库,当网络不稳定时,Maven构建会非常不稳定,甚至无法构建

远程仓库配置

若默认中央仓库无法满足项目需求,需配置其他远程仓库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<repositories>
<repository>
<id>bintray</id>
<url>http://dl.bintray.com/andsel/maven/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</repository>
</repositories>

repositories元素下,可以使用repository子元素声明一个或多个远程仓库,且任何一个仓库声明的id必须唯一,且Maven自带中央仓库idcentral若其它仓库声明也使用该id,会覆盖中央仓库的配置

url仓库地址,一般都基于http协议

releasessnapshots元素用来控制Maven对于发布版本构件快照版本构件的下载,releasesenabled值为true表示开启仓库发布版本下载支持snapshotsenabled值为false表示关闭仓库快照版本下载支持

updatePolicy元素用来配置Maven从远程仓库检查更新的频率默认daily每天检查更新一次never表示从不检查更新always表示每次构件都检查更新interval:X表示每隔X分钟检查更新一次(X为任意整数)

checksumPolicy元素用来配置Maven检查检验和文件的策略,当构件部署到Maven仓库时,会同时部署对应的检验和文件下载构件时会验证校验和文件checksumPolicy默认值为warn表示校验和文件验证失败在执行构建时输出警告信息fail表示让构建失败ignore表示完全忽略校验和错误

远程仓库认证

配置认证信息与配置仓库信息不同,仓库信息可直接配置在项目的POM文件中,但认证信息必须配置在setting.xml文件中,这样更为安全。

1
2
3
4
5
6
7
<servers>
<server>
<id>deploymentRepo</id>
<username>repouser</username>
<password>repopwd</password>
</server>
</servers>

servers元素下同样可以配置多个server,这里的id元素必须与POM中需要认证的repository元素的id完全一致

部署至远程仓库

要将项目生成的构件部署到仓库,需要在项目pom.xml中配置distributionManagement元素

1
2
3
4
5
6
7
8
9
10
11
12
<distributionManagement>
<repository>
<id>company-deploy</id>
<name>company-deploy</name>
<url>https://nexus.company.com/repository/company-deploy/</url>
</repository>
<snapshotRepository>
<id>company-snapshot-deploy</id>
<name>company-snapshot-deploy</name>
<url>https://nexus.company.com/repository/company-snapshot-deploy/</url>
</snapshotRepository>
</distributionManagement>

distributionManagement元素包含repository发布版本构件仓库和snapshotRepository快照版本仓库,id为该仓库的唯一标识,name为了方便阅读,url为该仓库地址。

命令行运行mvn clean deploy,Maven就会将项目构建输出的构件部署到配置对应的远程仓库,若当前版本是快照版本,则部署到快照版本仓库地址,反之部署到发布版本仓库地址

快照版本

任何一个项目或构件都必须有自己的版本,版本的值可能是1.0.01.3-alpha-43.02.1-SNAPSHOT2.1-20091216.221212-131.0.01.3-alpha-43.0稳定发布版本2.1-SNAPSHOT2.1-20091216.221212-13不稳定快照版本

使用快照版本,避免了在协同开发多个相互依赖的模块时,各个模块频繁更新POM,以及频繁代码更新造成的版本好滥用

当构件A的版本好设置为快照版本如2.1-SNAPSHOT时,在发布私服过程中,Maven会自动为构件打上时间戳,若构件B依赖与构件A的2.1-SNAPSHOT版本,当构建模块B时Maven会自动从远程仓库检查模块A的2.1-SNAPSHOT的最新构件,当发现更新时下载。默认每天检查一次,也可通过命令mvn clean install-U强制让Maven检查更新

快照版本只应该在组织内部的项目或模块间依赖使用,项目不应该依赖与任何组织外部的快照版本依赖,因为快照版本不稳定可能造成潜在风险

仓库解析依赖机制

依赖范围是system时,Maven直接从本地文件系统解析构件

根据依赖坐标计算仓库路径后,尝试直接从本地仓库寻找构件,若发现构件,则解析成功。

本地仓库不存在,若依赖版本是显示的发布版本构件,遍历所有远程仓库,发现后下载并解析使用。

若依赖版本是RELEASELATEST,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/maven-metadata.xml,将其与本地仓库对应的元数据合并后,计算出RELEASELATEST真实值,然后基于该真实值检查本地仓库和远程仓库

若依赖版本是SNAPSHOT,则基于更新策略读取所有远程仓库元数据groupId/artifactId/version/maven-metadata-snapshot.xml,将其与本地仓库对应的元数据合并,得到最新快照版本值,然后基于该值检查本地仓库和远程仓库

若最后解析得到的构件版本是时间戳格式的快照,则复制其时间戳格式的文件至非时间戳格式,并使用非时间戳格式的构件。

若当前版本不明晰的,如RELEASELATESTSNAPSHOT,Maven需要基于更新远程仓库的更新策略来检查更新。还可以使用-U参数强制检查更新,此时会忽略<updatePolicy>配置。

当Maven检查完更新策略,并决定检查依赖更新时,就需要检查仓库元数据maven-metadata.xmlLATEST指向了元数据中最新的那个版本,RELEASE指向了元数据中最新的发布版本。Maven通过合并多个远程仓库及本地仓库的元数据,就能计算出基于所有仓库的LATESTRELEASE,然后再解析具体的构件

不推荐在依赖声明中使用LATESTRELEASE,因为Maven随时都可能解析到不同的构件。Maven3不再支持在插件配置中使用LATESTRELEASE

不设置插件版本,其效果就和RELEASE一样,Maven会解析最新的发布版本构件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
<groupId>com.test</groupId>
<artifactId>web-core</artifactId>
<version>3.1.0-SNAPSHOT</version>
<versioning>
<snapshot>
<timestamp>20180831.035005</timestamp>
<buildNumber>11</buildNumber>
</snapshot>
<lastUpdated>20180831035005</lastUpdated>
<snapshotVersions>
<snapshotVersion>
<extension>jar</extension>
<value>3.1.0-20180831.035005-11</value>
<updated>20180831035005</updated>
</snapshotVersion>
</snapshotVersions>
</versioning>
</metadata>

timestampbuildNumber分别代表了这一快照的时间戳构件号

仓库元数据并不是永远正确的,若无法解析解析错误,可能出现了元数据错误,可以手工使用工具修复。

镜像

若仓库A能提供仓库B存储的所有内容,则A就是B的一个镜像,任何一个能从B仓库获得的构件都能从镜像中获取。http://maven.net.cn/content/groups/public/ 是中央仓库 http://repo1.maven.org/maven2 在中国的镜像。

1
2
3
4
5
6
7
8
<mirrors>
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
</mirrors>

mirrorOf的值为central,表示该配置为中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像。idnameurl与一般仓库配置无异,表示该镜像仓库的唯一标识符名称以及地址若需要认证也可以基于该id配置仓库认证

镜像的一个更常见的用法是结合私服私服就是所有仓库的镜像

<mirrorOf>*</mirrorOf>:匹配所有远程仓库

<mirrorOf>external: *</mirrorOf>:匹配所有远程仓库,使用localhost的除外,使用file://协议的除外。匹配所有不在本机上的远程仓库

<mirrorOf>repo1, repo2</mirrorOf>:匹配仓库repo1repo2,使用逗号分隔多个远程仓库。

<mirrorOf>*, !repo1</mirrorOf>:匹配所有远程仓库,repo1 除外,使用感叹号将仓库从匹配中排除

镜像仓库会完全屏蔽被镜像仓库当镜像仓库不稳定或停止服务时,Maven无法访问被镜像仓库,因而将无法下载构件

仓库搜索服务

Sonatype Nexus:提供的关键字搜索、类名搜索、坐标搜索、校验和搜索等功能。

Jarvana:提供基于关键字、类名的搜索,构件下载、依赖声明片段等功能。

Mvnbrowser:只提供关键字搜索,能告知用户构件依赖于哪些构件,以及该构件被哪些其他构件依赖。

MVNrepository:界面清新,提供关键字搜索、依赖声明代码片段、构件下载、依赖与被依赖关系信息、构件所包含信息等功能,提供一个简单图标,显示某个构件各个版本间的大小变化。