Maven详解之仓库------本地仓库、远程仓库
在Maven中,任何⼀个依赖、插件或者项⽬构建的输出,都可以称之为构件。
Maven在某个统⼀的位置存储所有项⽬的共享的构件,这个统⼀的位置,我们就称之为仓库。(仓库就是存放依赖和插件的地⽅)
任何的构件都有唯⼀的坐标,Maven根据这个坐标定义了构件在仓库中的唯⼀存储路径,
解读Maven在仓库中的存储路径:
1.基于groupId准备路径,将句点分隔符转成路径分隔符,就是将  "."  转换成 "/" ; example: stng --->org/testng
2.基于artifactId准备路径,将artifactId连接到后⾯:org/testng/testng
3.使⽤version准备路径,将version连接到后⾯:org/testng/testng/5.8
4.将artifactId于version以分隔符连字号连接到后⾯:org/testng/testng/
5.8/tesng-5.8
5.判断如果构件有classifier,就要在第4项后增加分隔符连字号再加上 classifier,org/testng/testng/5.8/tesng-5.8-jdk5
6.检查构件的extension,如果extension存在,则加上句点分隔符和extension,⽽extension是由packing决定
的,org/testng/testng/5.8/tesng-5.8-jdk5.jar
到这⾥我们就明⽩了Maven 对于构件存储的细节。
Maven 仓库的分类:
maven的仓库只有两⼤类:
1.本地仓库
2.远程仓库,在远程仓库中⼜分成了3种:
2.1 中央仓库
2.2 私服
2.3 其它公共库
1.本地仓库
顾名思义,就是Maven在本地存储构件的地⽅。
注:maven的本地仓库,在安装maven后并不会创建,它是在第⼀次执⾏maven命令的时候才被创建
maven本地仓库的默认位置:⽆论是Windows还是Linux,在⽤户的⽬录下都有⼀个.m2/repository/的仓库⽬录,这就是Maven仓库的默认位置
如何更改maven默认的本地仓库的位置:这⾥要引⼊⼀个新的元素:localRepository,它是存在于maven的l⽂件中
1.1 更改配置⽤户范围的本地仓库:
先在/.m2/⽬录下创建l⽂件,然后在~/.l,设置localRepository元素的值为想要的仓库地址
<settings xmlns="/SETTINGS/1.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/SETTINGS/1.0.0 /xsd/settings-1.0.0.xsd">
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository-->
<localRepository>D:/myworkspace/maven_repository</localRepository>
<!-- interactiveMode
| This will determine whether maven prompts you when it needs input. If set to false,
| maven will use a sensible default value, perhaps based on some other setting, for
| the parameter in question.
|
| Default: true
<interactiveMode>true</interactiveMode>
-->
...
...
这时候,maven的本地仓库地址就变成
了 D:\maven_new_repository ,注:此时配置的maven的本地仓库是属于⽤户范围的。
1.2 更改配置全局范围的本地仓库:
在M2_HOME/l(D:\soft\maven\apache-maven-3.3.l)中更改配置,更改配置的⽅法同上
注:此时更改后,所有的⽤户都会受到影响,⽽且如果maven进⾏升级,那么所有的配置都会被清除,所以要提前复制和备份
M2_HOME/l⽂件
故:⼀般情况下不推荐配置全局的l
1.3 ⼯程使⽤仓库配置的优先级顺序
这个确实是有个优先级的,应该是pom>⽤户级别>全局级别
例:如果pom中不配置,就取⽤户级别,如果⽤户级别也没有配置,就取全局级别
2. 远程仓库
2.1 说到远程仓库先从最核⼼的中央仓库开始,中央仓库是默认的远程仓库,maven在安装的时候,⾃带的就是中央仓库的配置
在maven的聚合与继承中我们说过,所有的maven项⽬都会继承超级pom,具体的说,包含了下⾯配置的pom我们就称之为超级pom
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>repo./maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
中央仓库包含了绝⼤多数流⾏的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。⼀般来说,简单的Java项⽬依赖的构件都可以在这⾥下载得到。
2.2 私服
私服是⼀种特殊的远程仓库,它是架设在局域⽹内的仓库服务,私服代理⼴域⽹上的远程仓库,供局域⽹内的Maven⽤户使⽤。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。我们还可以把⼀些⽆法从外部仓库下载到的构件上传到私服上。
Maven私服的个特性:
1.节省⾃⼰的外⽹带宽:减少重复请求造成的外⽹带宽消耗
2.加速Maven构件:如果项⽬配置了很多外部远程仓库的时候,构建速度就会⼤⼤降低
3.部署第三⽅构件:有些构件⽆法从外部仓库获得的时候,我们可以把这些构件部署到内部仓库(私服)中,供内部maven项⽬使⽤
4.提⾼稳定性,增强控制:Internet不稳定的时候,maven构建也会变的不稳定,⼀些私服软件还提供了其他的功能
5.降低中央仓库的负荷:maven中央仓库被请求的数量是巨⼤的,配置私服也可以⼤⼤降低中央仓库的压⼒
当前主流的maven私服:
1.Apache的Archiva
2.JFrog的Artifactory
3.Sonatype的Nexus
三、远程仓库配置
配置远程仓库将引⼊新的配置元素:<repositories>    <repository>
在<repositories>元素下,可以使⽤  <repository>⼦元素声明⼀个或者多个远程仓库。
例⼦:
<repositories>maven下载教程
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>repository.jboss/maven2/</url>
<releases>
<updatePolicy>daily</updatePolicy><!-- never,always,interval n -->
<enabled>true</enabled>
<checksumPolicy>warn</checksumPolicy><!-- fail,ignore -->
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<layout>default</layout>
</repository>
</repositories>
<updatePolicy>元素:表⽰更新的频率,值有:never, always,interval,daily, daily 为默认值
<checksumPolicy>元素:表⽰maven检查和检验⽂件的策略,warn为默认值
出于安全⽅⾯的考虑,有时我们要对远程仓库的访问进⾏认证,⼀般将认证信息配置在l中:
<servers>
<server>
<id>same with repository id in pom</id>
<username>username</username>
<password>pwd</password>
</server>
</servers>
注:这⾥的id必须与POM中需要认证的repository元素的Id⼀致。
如何将⽣成的项⽬部署到远程仓库
完成这项⼯作,也需要在POM中进⾏配置,这⾥有新引⼊了⼀个元素:<distributionManagement>
distributionManagement包含了2个⼦元素:repository和snapshotRepository, 前者表⽰发布版本构件的仓库,后者表⽰快照版本的仓库
这两个元素都需要配置 id(该远程仓库的唯⼀标识),name,url(表⽰该仓库的地址)
向远程仓库中部署构件,需要进⾏认证。配置同上
配置正确后运⾏: mvn clean deploy
正确的看待快照
之前我们在配置pom的时候,对于快照的配置都很谨慎,或者说很少⽤快照的版本,原因是它还很不稳定,极容易给我们的系统带来未知的错误,让我们很难查。其实快照版本也并不是⼀⽆是处,快照最⼤的⽤途是⽤在开发的过程中,尤其是有模块依赖的时候,⽐如说AB两个模块同时开发,A依赖于B,开发过程中AB都是持续集成的开发,不断的修改POM⽂件和构建⼯程,这时候版本同步就成了⼀个很⼤的问题。使⽤快照就可以达到这⼀⽬的。
其实在快照版本在发布的过程中,Maven会⾃动为构件以当前时间戳做标记,有了这个时间戳,我们就可以随时到最新的快照版本,这样也就解决刚才说的协作开发的问题。
⾄于A如何检查B的更新,刚刚在讲配置的时候说过,快照配置中有⼀个元素可以控制检查更新的频率------updatePolicy
我们也可以使⽤命令⾏加参数的形式强制执⾏让maven检查更新:
mvn clean install-U
maven到底是如何从仓库中解析构件的呢?----maven从仓库解析依赖的机制
1. 当依赖的范围是system的时候,Maven直接从本地⽂件系统解析构件
2. 根据依赖坐标计算仓库路径后,尝试直接从本地仓库寻构件,如果发现相应构件,则解析成功
3. 在本地仓库不存在相应的构件情况下,如果依赖的版本是显⽰的发布版本构件,则遍历所有的远程仓库,发现后下载使⽤
4. 如果依赖的版本是RELEASE或LATEST, 则基于更新策略读取所有远程仓库的元数据,将其于本地仓库的对应元数据合并后,计算出RELEASE或者LATEST的真实值,然后基于这个真实值检查本地仓库
5. 如果依赖的版本是SNAPSHOT,则基于更新策略读取所有远程仓库的元数据,将其与本地仓库的对应元数据合并后,得到最新快照版本的值,然后基于该值检查本地仓库或从远程仓库下载
6. 如果最后解析到的构件版本是时间戳格式的快照,则复制其时间戳格式的⽂件⾄⾮时间戳格式,并使⽤该⾮时间戳格式的构件
注:⼀定要记得<release>  <enabled>    &    <snapshot>  <enabled> ,对于快照也是⼀样
在POM的依赖声明的时候不推荐使⽤LATEST & RELEASE, 在Maven3中也不再⽀持在插件配置中使⽤LATEST & RELEASE,如果不设置插件版本,那么最终版本和release⼀样,
maven只会解析最新的发布版本构建。
1.远程仓库的配置
在平时的开发中,我们往往不会使⽤默认的中央仓库,默认的中央仓库访问的速度⽐较慢,访问的⼈或许很多,有时候也⽆法满⾜我们项⽬的需求,可能项⽬需要的某些构件中央仓库中是没有的,⽽在其他远程仓库中有,如JBoss Maven仓库。这时,可以在l中配置该仓库,代码如下:
1    <!-- 配置远程仓库 -->
2    <repositories>
3        <repository>
4            <id>jboss</id>
5            <name>JBoss Repository</name>
6            <url>repository.jboss/maven2/</url>
7            <releases>
8                <enabled>true</enabled>
9                <updatePolicy>daily</updatePolicy>
10            </releases>
11            <snapshots>
12                <enabled>false</enabled>
13                <checksumPolicy>warn</checksumPolicy>
14            </snapshots>
15            <layout>default</layout>
16        </repository>
17    </repositories>
repository:在repositories元素下,可以使⽤repository⼦元素声明⼀个或者多个远程仓库。
id:仓库声明的唯⼀id,尤其需要注意的是,Maven⾃带的中央仓库使⽤的id为central,如果其他仓库声明也使⽤该id,就会覆盖中央仓库的配置。
name:仓库的名称,让我们直观⽅便的知道仓库是哪个,暂时没发现其他太⼤的含义。
url:指向了仓库的地址,⼀般来说,该地址都基于http协议,Maven⽤户都可以在浏览器中打开仓库地址浏览构件。
releases和snapshots:⽤来控制Maven对于发布版构件和快照版构件的下载权限。需要注意的是enabled⼦元素,该例中releases的enabled值为true,表⽰开启JBoss仓库的发布版本下载⽀持,⽽snapshots的enabled值为false,表⽰关闭JBoss仓库的快照版本的下载⽀持。根据该配置,Maven只会从JBoss仓库下载发布版的构件,⽽不会下载快照版的构件。
layout:元素值default表⽰仓库的布局是Maven2及Maven3的默认布局,⽽不是Maven1的布局。基本不会⽤到Maven1的布局。
其他:对于releases和snapshots来说,除了enabled,它们还包含另外两个⼦元素updatePolicy和checksumPolicy。
元素updatePolicy⽤来配置Maven从远处仓库检查更新的频率,默认值是daily,表⽰Maven每天检查⼀次。其他可⽤的值包括:never-从不检查更新;always-每次构建都检查更新;interval:X-每隔X分钟检查⼀次更新(X为任意整数)。
元素checksumPolicy⽤来配置Maven检查校验和⽂件的策略。当构建被部署到Maven仓库中时,会同时
部署对应的检验和⽂件。在下载构件的时候,Maven会验证校验和⽂件,如果校验和验证失败,当checksumPolicy的值为默认的warn时,Maven会在执⾏构建时输出警告信息,其他可⽤的值包括:fail-Maven遇到校验和错误就让构建失败;ignore-使Maven完全忽略校验和错误。
2.远程仓库的认证
⼤部分公共的远程仓库⽆须认证就可以直接访问,但我们在平时的开发中往往会架设⾃⼰的Maven远程仓库,出于安全⽅⾯的考虑,我们需要提供认证信息才能访问这样的远程仓库。配置认证信息和配置远程仓库不同,远程仓库可以直接在l中配置,但是认证信息必须配
置在l⽂件中。这是因为pom往往是被提交到代码仓库中供所有成员访问的,⽽l⼀般只存在于本机。因此,在l中配置认证信息更为安全。
1 <settings>
2  2    ...
3  3    <!--配置远程仓库认证信息-->
4  4    <servers>
5  5        <server>
6  6            <id>releases</id>
7  7            <username>admin</username>
8  8            <password>admin123</password>
9  9        </server>
10 10    </servers>
11 11    ...
12 12 </settings>
上⾯代码我们配置了⼀个id为releases的远程仓库认证信息。Maven使⽤l⽂件中的servers元素及其⼦元素server配置仓库认证信息。认证⽤户名为admin,认证密码为admin123。这⾥的关键是id元素,l中server元素的id必须与l中需要认证的repository元素的id完全⼀致。正是这个id将认证信息与仓库配置联系在了⼀起。
3.部署构件⾄远程仓库
我们使⽤⾃⼰的远程仓库的⽬的就是在远程仓库中部署我们⾃⼰项⽬的构件以及⼀些⽆法从外部仓库直接获取的构件。这样才能在开发时,供其他对团队成员使⽤。
Maven除了能对项⽬进⾏编译、测试、打包之外,还能将项⽬⽣成的构件部署到远程仓库中。⾸先,需要编辑项⽬的l⽂件。配置distributionManagement元素,代码如下:
1 <distributionManagement>
2        <repository>
3            <id>releases</id>
4            <name>public</name>
5            <url>59.50.95.66:8081/nexus/content/repositories/releases</url>
6        </repository>
7        <snapshotRepository>
8            <id>snapshots</id>
9            <name>Snapshots</name>
10            <url>59.50.95.66:8081/nexus/content/repositories/snapshots</url>
11        </snapshotRepository>
12 </distributionManagement>
distributionManagement包含repository和snapshotRepository⼦元素,前者表⽰发布版本(稳定版本)构件的仓库,后者表⽰快照版本(开发测试版本)的仓库。这两个元素都需要配置id、name和url,id为远程仓库的唯⼀标识,name是为了⽅便⼈阅读,关键的url表⽰该仓库的地址。
往远程仓库部署构件的时候,往往需要认证,配置认证的⽅式同上。
配置正确后,运⾏命令mvn clean deploy,Maven就会将项⽬构建输出的构件部署到配置对应的远程仓库,如果项⽬当前的版本是快照版本,则部署到快照版本的仓库地址,否则就部署到发布版本的仓库地址。
快照版本和发布版本的区别请⾃⾏上百度查阅资料。
4.配置远程仓库的镜像
1 <mirrors>
2      <mirror>
3      <id>maven.oschina</id>
4      <name>maven mirror in China</name>
5      <url>maven.oschina/content/groups/public/</url>
6      <mirrorOf>central</mirrorOf>
7    </mirror>
8 </mirrors>
该例中,mirrorOf的值为central,表⽰该配置为中央仓库的镜像,任何对于中央仓库的请求都会转⾄该镜像,⽤户也可以使⽤同样的⽅法配置其他仓库的镜像。id表⽰镜像的唯⼀标识符,name表⽰镜像的名称,url表⽰镜像的地址。
关于镜像的⼀个更为常见的⽤法是结合私服。由于私服可以代理任何外部的公共仓库(包括中央仓库),因此,对于组织内部的Maven⽤户来说,使⽤⼀个私服地址就等于使⽤了所有需要的外部仓库,这可以将配置集中到私服,从⽽简化Maven本⾝的配置。在这种情况下,任何需要的构件都可以从私服获得,私服就是所有仓库的镜像。这时,可以配置这样的⼀个镜像:
1 <!--配置私服镜像-->
2 <mirrors>
3    <mirror>
4        <id>nexus</id>
5        <name>internal nexus repository</name>