Maven 仓库简介

何为 Maven 仓库

在 Maven 世界中,任何一个依赖、插件或者项目构建的输出,都可称为构件。任何一个构件都有一组坐标来唯一标识。得益于坐标机制,任何 Maven 项目使用任何一个构件的方式都是完全相肉中刺的。据此,Maven 可以在某个地方统一存储管理所有 Maven 项目共享的构件,实际的 Maven 项目将不再各自存储其依赖文件而只需要声明这些依赖的坐标,这个存储的地方就是仓库。Maven 通过仓库来统一管理构件的物理文件。

为了实现重用,项目构建完成后生成的构件也可以安装和部署到仓库,以供其他开发人员和项目使用。

Maven 仓库的分类

原格来说,Maven 仓库只有两类:本地仓库和远程仓库。当 Maven 根据坐标寻找构件时,首先会查看本地仓库,找到则直接使用;如果本地仓库不存在此构件,或者需要检查构件是否更新,Maven 就会去远程仓库查找,找到后下载到本地仓库再使用。如果本地仓库和远程仓库都没有需要的构件,则报错。

这里,将远程仓库进一步分为中央仓库、私服和其他公共库,以便说明。

本地仓库

一般来说,在 Maven 项目目录下,没有诸如 lib/ 这样目录用来存放依赖文件。当 Maven 在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依赖文件。

本地仓库在本机缓存着从远程仓库下载而来的构件拷贝,以及尚未发布的本地 Maven 项目的临时构建产生的构件输出。一个构件只有在本地仓库中之后,才能由其他 Maven 项目使用。

不管是在 Windows 还是 Linux 上,本地仓库缺省是在用户目录下一个路径名为 .m2/repository/ 的目录。本地仓库的目录位置是可配置的。初始如果不执行任何 Maven 命令,本地仓库目录是不存在的。当用户执行第一条 Maven 命令之后,Maven 才会创建本地仓库。

远程仓库

远程仓库可以是一个直正意义的需要通过各种网络协议(如 “file:” 和 “http:”)来进行访问的远程终端库。也可以是公司、团体内部使用的那种架设在局域网或外网的一个文件或 HTTP 服务器上的库,用于在团队和项目间分享私有构件。

中央仓库

初始的本地仓库是空的,Maven 必须知道至少一个可用的远程仓库,才能在执行 Maven 命令时下载到需要的构件。中央仓库就是这样一个默认的远程仓库,是一个真正意义的远程仓库。

Maven 的安装文件自带了中央仓库的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<repositories>
<repository>
<!-- 中内仓库唯一标识 -->
<id>central</id>
<name>Maven Repository Switchboard</name>
<!-- 访问地址 -->
<url>http://repo1.maven.org/maven2</url>
<layout>default</layout>

<snapshots>
<!-- 表示不从该仓库下载快照版本的构件 -->
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

私服

私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的 Maven 用户使用。当 Maven 需要下载构件的时候,它从私服请求,如果么服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为 Maven 的下载请求提供服务。此外,一些无法从外部仓库下载到的构件也能从本地上传到私服上供项目共享。

私服的优点:

  • 节省外网带宽;
  • 加速 Maven 构建;
  • 部署第三方构件;
  • 提高稳定性,增强控件;
  • 降低中央仓库的负荷。

流行的 Maven 私服软件,如 Nexus 等。

Maven 仓库的配置

本地仓库配置

因为硬盘空间等原因,有时会想要自定义本地仓库目录地址。这时,可以编辑文件 ~/.m2/settings.xml,设置 <localRepository> 元素的值为想要的仓库地址。例如:

1
2
3
<settings>
<localRepository>/home/username/MavenLocalRepository/</localRepository>
</settings>

注意:
settings.xml 一般只放在本机。文件格式及内容可参考或从 $M2_HOME/conf/settings.xml 拷贝修改。

远程仓库配置

  • 配置远程仓库

有时,默认的中央仓库无法满足项目的需要,项目依赖的构件存在于另外的远程仓库中,这就需要对远程仓库进行配置。在 <repositories> 元素下,可以使用 <repository> 子元素声明一到多个远程仓库。

例如,配置 JBoss Maven 仓库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<project>
...
<repositories>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.com/maven2/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
...
</project>

注意:

  • 任何一个仓库的声明的 id 必须是唯一的。Maven 自带的中央仓库使用的 id 为 central,如果其他的仓库声明也使用该 id,就会覆盖中央仓库的配置。
  • 配置中的 URL 值指向了仓库的地址,通常都基于 http 协议,可以在浏览器中打开仓库地址浏览构件。
  • 配置中的 <releases> 和 <snapshots> 元素,用来控制 Maven 对于发布版构件和快照构件的下载。
    <enabled> 子元素:用于打开/关闭 Maven 对于发布版构件和快照构件的下载。
    <updatePolicy> 子元素:用来配置 Maven 从远程仓库检查更新的频率,缺省值为 daily,表示每天检查一次。可选值还包括:never(从不检查更新)、always(每次构建都检查更新)、interval:x(每隔x分钟检查一次更新,x为整数)。
    <checksumPolicy> 子元素:用来配置 Maven 检查检验和文件的策略,缺省值为 warn(输出警告)。可选值还包括:fail(校验错误则让构建失败)、ignore(忽略校验错误)。当部署 Maven 构件时,会同时部署对应的检验和文件。在下载构件时,Maven 会验证检验和文件。
1
2
3
4
5
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</snapshots>
  • 配置仓库认证信息

如果管理员为仓库提供了用户名和密码,为了能让 Maven 访问仓库,需要配置认证信息。Maven 使用 settings.xml 文件中的 <servers> 元素及其 <server> 子元素配置仓库谁信息。<server> 元素的 id 必须与 POM 中需要认证的 repository 元素的 id 完全一致。

1
2
3
4
5
6
7
8
9
10
11
<settings>
...
<servers>
<server>
<id>myproj</id>
<username>repo-user</username>
<password>repo-pwd</password>
</server>
</servers>
...
</settings>

部署配置

私服的一大作用是部署第三方构件,包括组织内部生成的构件以及一些无法从外部仓库直接获取的构件。Maven 可以通过配置 <distributionManagement> 元素来将项目生成的构建部署到仓库中。

  • 配置部署项目构件到远程库:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<proejct>
...
<distributionManagement>
<repository>
<uniqueVersion>false</uniqueVersion>
<id>corp1</id>
<name>Corporate Repository</name>
<url>scp://repo/maven2</url>
<layout>default</layout>
</repository>
<snapshotRepository>
<uniqueVersion>true</uniqueVersion>
<id>propSnap</id>
<name>Propellors Snapshots</name>
<url>sftp://propellers.net/maven</url>
<layout>legacy</layout>
</snapshotRepository>
...
</distributionManagement>
...
</project>
  • 部署 Maven 项目的网站和文档:
1
2
3
4
5
6
7
8
9
10
11
12
<proejct>
...
<distributionManagement>
<site>
<id>com.company.proj</id>
<name>Company Project Website</name>
<url>scp://www.company.com/home/projects/proj/public_html/</url>
</site>
...
</distributionManagement>
...
</project>
  • 配置将当前 Maven 项目以新的构件的形式发布到另一个库:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<proejct>
...
<distributionManagement>
...
<relocation>
<groupId>org.apache</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
<message>We have moved the Project under Apache</message>
</relocation>
...
</distributionManagement>
...
</project>

镜像

如果仓库 X 可以提供仓库 Y 存储的所有内容,那么就可以认为 X 是 Y 的一个镜像。考虑到地理位置的因素,可以考虑为远程仓库配置一个本地镜像,以提供更快的服务。

如编辑 settings.xml 来配置 Maven 镜像以替代中央仓库。

1
2
3
4
5
6
7
8
9
10
11
12
13
<settings>
...
<mirrors>
<mirror>
<id>internal-repository</id>
<name>Internal Repository Mirror</name>
<url>http://192.168.1.100/maven2/</url>

<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
...
</settings>

mirror 中 id、name、url 子元素与一般仓库配置无异,表示该镜像仓库的唯一标识符、名称以及地址。<mirrorOf> 的值为 central,表示该配置为中央仓库的镜像,任何对于中央仓库的请求都会转到该镜像。

<mirrorOf> 配置规则:

  • <mirrorOf>*</mirrorOf>:匹配所有远程仓库。
  • <mirrorOf>external:*</mirrorOf>:匹配所有远程仓库,使用 localhost 的除外。
  • <mirrorOf>repo1,repo2</mirrorOf>:匹配仓库 repo1 和 repo2,使用逗号分隔多个远程仓库。
  • <mirrorOf>*,!repo1</mirrorOf>:匹配所有非repo1远程仓库。

参考资源

显示 Gitment 评论