maven仓库
- 什么是maven仓库
一个管理项目构件的地方,统一管理构件,然后提供给不同的项目使用;一方面提高了构件的复用性,另一份提高了效率。在没有仓库之前,通常会新建一个lib文件夹,用于存放jar包。相同的依赖,各种粘贴复制。有了仓库之后,项目只需申明引用即可,在打包的时候,会自动将需要的包合并打包,从而去除了很多重复的操作。
- 仓库结构
| --- 本地仓库
| --- 远程仓库
| --- --- 中央仓库
| --- --- 私服(内网)
| --- --- 第三方公有仓库
本地仓库
本地仓库:实际就是.m2/repository仓库,用于管理本地项目构件。
- 修改本地仓库
默认情况下,本地仓库:.m2/repository,不过可以通过修改settings.xml配置来指定本地仓库位置;
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
前面提到了关于settings.xml配置的作用域问题,可以设置全局,也可以在用户目录下的.m2/settings.xml(默认不存在,需要自己创建);
- 本地仓库构件来源
本地仓库的构件是如何获取以及管理运行的,需要明确2点:
1、从远程仓库下载:当项目中引用构件时,会先从本地仓库查找,如果存在,那么直接引用,如果不存在,那么本地仓库会根据你设置的远程仓库进行下载,下载到本地仓库之后,再提供给项目使用;
2、本地安装构件到仓库:当项目开发完成之后发布构件,为了可以使用其他项目使用,需要先将其安装到本地仓库才能使其他本地项目使用,可以通过: mvn install,目的就是将当前构件安装到本地仓库。
- 什么时候创建本地仓库
安装好maven之后,如果不做任何操作maven命令,本地仓库不会创建的,当输入第一条maven命令时,会触发创建本次仓库。
远程仓库
远程仓库可以直接理解为就是不是自己的仓库,是别人提供的仓库。遵循的原则就是:先查找本地仓库,没有然后再远程仓库。
中央仓库
所谓的中央仓库,就是本地仓库设置的远程仓库,当本地仓库没有时,就会从这个指定的地址下载构件。
- 中央仓库配置
默认配置在$M2_HOME/lib/maven-model-builder.jar中,org/apache/maven/model/pom-4.0.0.xml 中;
代码摘自:org/apache/maven/model/pom-4.0.0.xml
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<!-- 不使用快照版本 -->
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
这个pom是所有pom的父级,因此所有项目都默认使用这个仓库。
私服
私服:设置在局域网内用于代理广域网的远程仓库的特殊仓库。说白了就是:公司内部的maven仓库,大家都使用这个仓库,然后这个仓库去其设置的远程仓库下载构建。
优点:可以统一仓库使用,减少重复下载构件;
缺点:私服挂了,就拜拜了;当然也可以通过做一些配置,做降级处理(这里不做介绍);
如果是公司级别的使用,还是推荐私服方式,不仅可以统一仓库的使用,也可以有效管理构件。
- 私服运行结构
| -- maven client -------------------- 中央仓库
| \ \ /
| 下载 上传 下载
| \ \ /
| --------> 私服 ----->----下载---- 第三方仓库(Jboss仓库)
远程仓库配置
我们也可以自定义远程仓库,在pom.xml定义;
<repositories>
<repository>
<id>maven-remote-repo</id>
<name>study maven remote repository</name>
<!-- 仓库地址 -->
<url>https://repository.jboss.org/maven2</url>
<!-- 配置下载构件时,是否只下载release版本 -->
<releases>
<enabled>true</enabled>
</releases>
<!-- 配置下载构件时,是否可以下载Snapshot版本 -->
<snapshots>
<enabled>false</enabled>
</snapshots>
<!-- 标识仓库的布局,maven2/3是默认布局 -->
<layout>default</layout>
</repository>
</repositories>
- 仓库的认证
一些远程仓库访问是需要用户认证的,比如:私服。因此我们需要针对远程仓库访问进行用户信息配置(settings.xml)。
<servers>
<!-- server
| Specifies the authentication information to use when connecting to a particular server, identified by
| a unique name within the system (referred to by the 'id' attribute below).
|
| NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
| used together.
|
-->
<server>
<!-- 这里的ID就是 repositories/repostory/id 标签设置的 -->
<id>maven-remote-repo</id>
<username>test</username>
<password>test</password>
</server>
</servers>
- SNAPSHOT (快照)
一般版本分为:
1、快照版:表示当前处于开发阶段;
2、发布版:表示已经发布生产,外部可以引用;
为啥要快照版本?
在联合开发时,会存在相互依赖的情况,例如:A项目依赖B项目,那么在A项目开发时需要引入B项目的jar。我们需要一种解决方案,帮助我们B项目开发专注在B上,A项目专注在A上,如果B在开发中发生变化,A可以能够得到及时的反馈,但是又不需要耗费太多精力。这就诞生了快照版本,一种定义在开发中的版本,不稳定的版本。
在maven中,如果是SNAPSHOT(快照)版本,在依赖引入时,会定时去更新最新的快照版本内容(通过updatePolicy)来设置,会生成时间戳版本:例如, 2.1-20170816.121212-10 标识2.1快照版本,2017.08.16 12:12:12 第10次更新。
如果使用快照版本?
快照版本经常用于开发阶段,待可以完全发布的版本,就应该去掉快照版本。项目本身不应该去依赖外部的快照版(在发布前,应该确保引用的是非快照版本,快照版本会根据更新策略,不断更新内容,是不稳定的版本)。
简单概述:就是开发时使用快照版本,上线前应该修改为稳定版本。(1.0-SNAPSHOT -> 1.0)
仓库设置快照版本
<snapshots>
<!-- true:支持引入快照 -->
<enabled>true</enabled>
<!-- 更新策略: 从不、每天、总是、定时 -->
<updatePolicy>never|daily|always|interval</updatePolicy>
<!-- 验证策略:警告、致命、不管的 -->
<checksumPolicy>warn|fail|ignore</checksumPolicy>
</snapshots>
- 仓库解析依赖机制
针对的本地仓库从远程仓库下载时,如何确定要下载的构件,在我们配置仓库的时候,有releases, snapshots相关的配置,主要配置是否支持,更新策略、验证策略;
1、当依赖SNAPSHOT版本时,会从远程仓库获取maven-metadata.xml和本地仓库的maven-metadata.xml合并,最终确认是从远程仓库下载还是本地仓库获取。(从而可以获取最新的快照版本)
2、当依赖Release或者latest时,如果依赖的是指定的版本(例如:1.0),那么会检查本地仓库是否存在,没有就会从远程仓库下载;
详情参考:http://fhd001.iteye.com/blog/1191037
maven-metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus</artifactId>
<versioning>
<!-- 最新版本,可能是快照版 -->
<latest>1.4.2-SNAPSHOT</latest>
<!-- 最新发布版 -->
<release>1.4.0</release>
<versions>
<version>1.3.5</version>
<version>1.3.6</version>
<version>1.4.0-SNAPSHOT</version>
<version>1.4.0</version>
<version>1.4.0.1-SNAPSHOT</version>
<version>1.4.1-SNAPSHOT</version>
<version>1.4.2-SNAPSHOT</version>
</versions>
</versioning>
</metadata>
详情参考:http://maven.apache.org/ref/3.2.5/maven-repository-metadata/index.html
建议实践
开发中使用SNAPSHOT,如果是生产最好使用稳定发布版(指定版本),如果不指定版本,可能会使用到最新的发布版,出现1.1和1.2接口不兼容的情况。因此在pom.xml中,最好明确version。
镜像
所谓的镜像,可以理解为是原始对象的copy对象。在maven中的镜像,任何可以提供原始仓库提供的服务,都可以认为是镜像,如果要访问原始仓库,可以通过只访问镜像仓库就可以。经常会结合私服来使用。可以将私服配置为镜像。
- 配置镜像
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
| -->
<mirror>
<id>mirrorId</id>
<!-- 匹配逻辑(仓库ID)
<mirrorOf>*</mirrorOf> 拦截所有的仓库访问
<mirrorOf>rep1,rep2</mirrorOf> 拦截指定的仓库访问
<mirrorOf>external:*</mirrorOf> 拦截所有仓库访问,除了所有本机上的远程仓库(file:///, localhost)
<mirrorOf>*,!rep1,!rep2</mirrorOf> 拦截所有仓库访问,除了rep1,rep2
-->
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<!-- 转接到指定的URL,例如:私服地址 -->
<url>http://my.repository.com/repo/path</url>
</mirror>
</mirrors>
参考
[1] http://fhd001.iteye.com/blog/1191037
[2] http://maven.apache.org/ref/3.2.5/maven-repository-metadata/index.html