2015年12月26日星期六

Maven_003:设置本地仓库和远程仓库

环境: OS X EI Capitan 10.11.2 + JDK 1.8.0_66 + Maven 3.3.9

构件在仓库中的路径为: groupId/artifactId/version/artifactId-version-classifier.packaging。

Maven仓库分为本地仓库和远程仓库这两种,首先从本地仓库去找构件,如果存在,则直接使用;如果不存在,去远程仓库查找,找到后,下载到本地仓库。
如果本地仓库和远程仓库都没有找到需要的构件,Maven会报错。
中央仓库Maven核心自带的远程仓库,默认情况下,当本地仓库没有构件的时候,就会从中央仓库下载。
私服是一种特殊的远程仓库,是假设在局域网内的私有仓库,用其代理所有的远程仓库。
除了中央仓库和私服,还有很多其它公开的远程仓库,比如JBoss Maven 库:http://repository.jboss.org/maven2/。

1. 设置本地仓库
默认情况下,本地仓库指向~/.m2/repository目录。
要指向其它目录,需要修改~/.m2/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>
-->

2. 私服
私服是指在局域网内部搭建的 repository,它跟 central repository,jboss repository等的区别仅仅在于其 URL 是一个内部网址。

3. 设置远程仓库
远程仓库既可以设置在pom.xml中,也可以设置在settings.xml文件中。

 <project>
    ...
    <repositories>
        <repository>
          <id>jdk14</id>
          <name>Repository for JDK 1.4 builds</name>
          <url>http://www.myhost.com/maven/jdk14</url>
          <layout>default</layout>
          <snapshotPolicy>always</snapshotPolicy>
        </repository>
    </repositories>
    ...
 </project>

(1)仓库的id必须唯一。
(2)releases的enable值为true,表示开启发布版本的下载支持。
(3)snapshots的enable值为false,表示关闭快照版本的下载支持。
(4)layout 表示使用Maven 2 或 3 的布局。
(5)updatePolicy 表示从远程仓库的更新频率,默认是daily,每天检查;never,从不检查;always,每次构建都检查更新;X,每隔X分钟检查一次。
(6)checksumPolicy 表示部署构件时,会同时部署对应的校验文件;下载构件时,会验证校验文件。该值为 warn 时,提示警告;为 fail 时,构建失败;为 ignore 时,忽略错误。 

4. 配置远程仓库的认证
远程仓库的认证只能设置在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>deploymentRepo</id>
      <username>repouser</username>
      <password>repopwd</password>
    </server>
    -->

    <!-- Another sample, using keys to authenticate.
    <server>
      <id>siteServer</id>
      <privateKey>/path/to/private/key</privateKey>
      <passphrase>optional; leave empty if not used.</passphrase>
    </server>
    -->
</servers>

5. 部署构件到远程仓库
在pom.xml中设置远程仓库:

<distributionManagement>
    <repository>
        <id>releases</id>
        <name>Nexus Release Repository</name>
        <url>http://localhost:8081/nexus/content/repositories/releases/</url>
    </repository>
    <snapshotRepository>
        <id>snapshots</id>
        <name>Nexus Snapshot Repository</name>
        <url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
    </snapshotRepository>
</distributionManagement>

(1)releases 是发布版本的构件,项目外部的依赖应该都是发布版本的构件。
(2)snapshots 是快照版本的构件,快照版本的构件只应该用于项目内部的模块依赖。
(3)repository 中的 id 必须与 server 中的 id 一致。

运行 mvn clean deploy,部署构件到远程仓库,发布版本会部署到发布版本的远程仓库;快照版本会部署到快照版本的远程仓库。

6. 镜像
仓库 X 能够提供仓库 Y 的所有内容,那么仓库 X 就是仓库 Y 的一个镜像。
配置镜像后,本来需要从仓库 Y 下载构件的请求会转到仓库 X。
在 settings.xml 中增加镜像的配置:

例1:指定仓库的镜像
<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>
      <mirrorOf>repositoryId</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>http://my.repository.com/repo/path</url>
    </mirror>
     -->
</mirrors>
说明:
(1)mirrorOf 指定镜像的repositoryId。也可以以逗号间隔,指定多个远程库。

例2:中央仓库的镜像
<settings>
  ...
  <mirrors>
    <mirror>
      <id>maven.net.cn</id>
      <name>one of the central mirrors in china</name>
      <url>http://maven.net.cn/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
  ...
</settings>
说明:
(1)mirrorOf 指定镜像的repositoryId,这里 central 表示中央仓库。也可以以逗号间隔,指定多个远程库。

例3:所有仓库的镜像
关于镜像的一个更为常见的用法是结合私服。由于私服可以代理任何外部的公共仓库,因此,对于组织内部的 Maven 用户来说,使用一个私服地址就等于使用了所有需要的外部仓库,这可以将配置集中到私服,从而简化 Maven 本身的配置。在这种情况下,任何需要的构件都可以从私服获得,私服就是所有仓库的镜像。  

<settings>
  ...
  <mirrors>
    <mirror>
      <id>internal-repository</id>
      <name>Internal Repository Manager</name>
      <url>http://192.168.1.100/maven2</url>
      <mirrorOf>*</mirrorOf>
    </mirror>
  </mirrors>
  ...
</settings>

说明:
(1) <mirrorOf>*</mirrorOf> ,表示该配置是所有 Maven 仓库的镜像,任何对于远程仓库的请求都会被转至 http://192.168.1.100/maven2/。
如果该镜像仓库需要认证,则配置一个 id 为 internal-repository 的 <server> 即可。
(2) <mirrorOf>external:*</mirrorOf> ,表示匹配所有远程仓库,使用localhost 的除外,使用 file:// 协议的除外。也就是说,匹配所有不在本机上的远程仓库。
(3) <mirrorOf>repo1,repo2</mirrorOf> ,表示匹配仓库 repo1 和 repo2,使用逗号分隔多个远程仓库。 
(4) <mirrorOf>*,!repo1</miiroOf> ,表示匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中排除。

需要注意的是,由于镜像仓库完全屏蔽了被镜像仓库,当镜像仓库不稳定或者停止服务的时候,Maven 将无法访问被镜像仓库,因此也将无法下载构件。

7. 私服与镜像的区别
私服本身是一个 repository,可以和其它 repository 一起提供服务,比如它可以用来提供公司内部的 maven 构件。
镜像相当于一个代理,它会拦截去指定的远程 repository 下载构件的请求,然后从自己这里找出构件回送给客户端。镜像本身并不是 repository,它只是远程 repository 的网络加速器,配置镜像的目的一般是出于网速考虑。

可以看出,私服和镜像两个不同的东西。
不过很多私服搭建工具本身也提供镜像服务,比如 Nexus 就可以让同一个 URL 既用作internal repository,又使它成为所有 repository 的 mirror。

参考文献:
1. 《Maven 实战》 徐晓斌著

没有评论: