Maven学习总结系列五:仓库

坐标和依赖是任何一个构件在Maven世界中的逻辑表示方式; 而构件的物理表示方式则是文件。

那么Maven又是怎么去管理这些构件文件的呢?

Maven通过仓库来统一管理这些文件。

开发中的问题:

在一台工作站中,可能有几十个Maven项目,都使用log4j,如果在每一个项目都放一份重复的log4j文件,会造成磁盘空间的浪费,而且也难于统一管理,文件的复制等操作也会降低构建的速度。

在不使用Maven的那些项目,我们在lib/目录下,内容存在大量的重复。

如何避免构件的重复存储?

Maven的方案:

由于坐标的机制,所有Maven项目要引用依赖时,都是使用相同的坐标。在此基础上,Maven可以在某个位置统一存储所有的Maven项目共享的构件,这个统一的位置就是“仓库”。

在使用是,maven的项目也不再各自存储其依赖文件,而只需要声明这些依赖的坐标,在需要的时候(如:编译项目时需要将依赖加入到classpath),Maven会自动根据坐标找到仓库中的构件,并使用它们。

同时构建完毕后生成的构件也会安装或部署到仓库中,供其它项目使用。

如:我们在pom.xml中引入了spring-core的依赖,Maven会到“本地仓库”去查找这个构件,并引入进来。从spring-core-2.5.6.jar包的位置可以看到,它是在本地仓库中的,并没有在项目的lib中。

--------------------------------------------------------------------------

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>2.5.6</version>

</dependency>

--------------------------------------------------------------------------

 

1.2 仓库的布局

Maven仓库布局方式:任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径。

存储路径与坐标大概对应关系:

groupId/artifactId/version/artifactId-version.packaging

如:struts-1.2.9.jar的坐标如下,

--------------------------------

<modelVersion>4.0.0</modelVersion>

  <groupId>struts</groupId>

  <artifactId>struts</artifactId>

  <version>1.2.9</version>

---------------------------

它的存储位置如下:

D:\Workspaces\maven_repository\struts\struts\1.2.9>dir

 Volume in drive D has no label.

 Volume Serial Number is DEE4-849E

 Directory ofD:\Workspaces\maven_repository\struts\struts\1.2.9

11/22/2017  11:52 PM   <DIR>          .

11/22/2017  11:52 PM   <DIR>          ..

11/22/2017  11:52 PM               345 m2e-lastUpdated.properties

11/22/2017  11:52 PM               401struts-1.2.9-javadoc.jar.lastUpdated

11/22/2017  11:52 PM           925,381 struts-1.2.9-sources.jar

11/22/2017  11:52 PM                40struts-1.2.9-sources.jar.sha1

11/22/2017  11:13 PM           549,876 struts-1.2.9.jar

11/22/2017  11:13 PM                40 struts-1.2.9.jar.sha1

11/22/2017  10:47 PM             9,461 struts-1.2.9.pom

11/22/2017  10:47 PM                40 struts-1.2.9.pom.sha1

11/22/2017  11:52 PM               218 _remote.repositories

               9 File(s)      1,485,802 bytes

               2 Dir(s)  212,865,761,280 bytes free

Maven的源码并结合具体的实例来理解Maven仓库的布局方式:

privatestatic final char PATH_SEPARATOR = '/';

privatestatic final char GROUP_SEPARATOR = '.';

privatestatic final char ARTIFACT_SEPARATOR = '-';

public String pathOf( Artifact artifact )

{

ArtifactHandlerartifactHandler = artifact.getArtifactHandler();

StringBuilderpath = new StringBuilder( 128 );

path.append(formatAsDirectory( artifact.getGroupId() )).append( PATH_SEPARATOR );

path.append(artifact.getArtifactId() ).append(PATH_SEPARATOR );

path.append(artifact.getBaseVersion() ).append(PATH_SEPARATOR );

path.append(artifact.getArtifactId() ).append( ARTIFACT_SEPARATOR ).append(artifact.getVersion() );

if (artifact.hasClassifier() )

{

path.append(ARTIFACT_SEPARATOR ).append( artifact.getClassifier() );

}

if (artifactHandler.getExtension() != null &&artifactHandler.getExtension().length() > 0 )

{

path.append(GROUP_SEPARATOR ).append( artifactHandler.getExtension() );

}

returnpath.toString();

}

private StringformatAsDirectory( String directory )

{

return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );

}

该pathOf()方法的目的是根据构件信息生成其在仓库中的路径。考虑这样一个构件:groupId=org.testng、artifactId=testng、version=5.8、classifier=jdk15、packaging=jar,其对应的路径按如下步骤生成:

  1. 首先基于构件的groupId准备路径,formatAsDirectory()将groupId中的句点分隔符转换成路径分隔符,该例中,groupId org.testng就会被转换成org/testng,之后再加一个路径分隔符斜杠,那么org.testng就成为了org/testng/。
  2. 基于构件的artifactId准备路径,也就是在前面的基础上加上artifactId以及一个路径分隔符,该例中的artifactId为testng,那么在这一步过后路径就成为了org/testng/testng/。
  3. 接着使用版本信息,在前面的基础上加上version和路径分隔符,该例中版本是5.8,那么路径就成为了org/testng/tesgng/5.8/。
  4. 这一步再依次加上artifactId,构件分隔符连字号,以及version,于是构建的路径就变成了org/testng/testng/5.8/testng-5.8。读者可能会注意到这里使用了artifactId.getVersion(),而上一步用的是artifactId.getBaseVersion(),version和baseVersion的区别在本章讨论SNAPSHOT的时候会具体阐述。
  5. 紧接着如果构件有classifier,就加上构件分隔符和classifier,该例中构件的classifier是jdk15,那么路径就变成org/testng/testng/5.8/testng-5.8-jdk5。
  6. 最后第检查构件的extension,若extension存在,则加上句点分隔符和extension,从代码中可以看到,extension是从artifactHandler而非artifact获取,artifactHandler是由项目的packaging决定的,因此可以说,packaging决定了构件的扩展名,该例的packaging是的jar,因此最终的路径为org/testng/testng/5.8/testng-5.8-jdk5.jar。

由于Maven仓库是基于简单文件系统存储的,现在我们又理解了其存储方式,因此当遇到一些与仓库相关的问题时,可以很方便的查找相关文件,方便定位问题。例如当Maven无法获得项目声明的依赖时,可以简单该依赖对应的文件在仓库中是否存在,如果不存在,是否有其它版本可用,等等。

1.3 仓库的分类

Maven分为两类:本地仓库和远程仓库。

Maven到仓库查找构件逻辑:

本地仓库-Y->远程仓库-Y->下载到本地仓库-->使用

                 -N->使用     -N->报错

 

1.3.1 本地仓库

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

本地仓库默认路径:

1.安装的地方:${M2_HOME}/conf/settings.xml

2.用户的目录:${user.home}/.m2/settings.xml

前者又被叫做全局配置,对操作系统的所有使用者生效;

后者被称为用户配置,只对当前操作系统的使用者生效。

如果两者都存在,它们的内容将被合并,并且用户范围的settings.xml会覆盖全局的settings.xml。

Maven安装后,用户目录下不会自动生成settings.xml,只有全局配置文件。如果需要创建用户范围的settings.xml,可以将安装路径下的settings复制到目录${user.home}/.m2/。Maven默认的settings.xml是一个包含了注释和例子的模板,可以快速的修改它来达到你的要求。

全局配置一旦更改,所有的用户都会受到影响,而且如果maven进行升级,所有的配置都会被清除,所以要提前复制和备份${M2_HOME}/conf/settings.xml文件,一般情况下不推荐配置全局的settings.xml。

6.3.2 远程仓库

对于Maven来说,每个用户只有一个本地仓库,但可以配置访问很多远程仓库。根据Maven查找artifact的原理,Maven会先从“本地仓库”中查找artifact,找不到就会到配置的”远程仓库“中找,然后下载到”本地仓库“,再使用。

本地仓库:类似于我们自己的书房。

远程仓库:类似于外面各大图书馆,我们可以从各大图书馆,书店租/买书回来,充实我们自己的书房,然后在自己的书房看书。

1.3.3 中央仓库

最原始的”本地仓库“是空的,Maven必须知道至少一个可用的远程仓库,才能在执行Maven命令的时候下载需要的构件。

而”中央仓库“就是这样一个默认的远程仓库,Maven的安装文件自带了中央仓库的配置。

 

 

------------------------------------------------------------------------

<?xmlversion="1.0" encoding="UTF-8"?>

<!--

Licensed to theApache Software Foundation (ASF) under one

or more contributorlicense agreements.  See the NOTICE file

distributed withthis work for additional information

regarding copyrightownership.  The ASF licenses this file

to you under theApache License, Version 2.0 (the

"License");you may not use this file except in compliance

with theLicense.  You may obtain a copy of theLicense at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required byapplicable law or agreed to in writing,

software distributedunder the License is distributed on an

"AS IS"BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

KIND, either expressor implied.  See the License for the

specific languagegoverning permissions and limitations

under the License.

-->

<!-- STARTSNIPPET: superpom -->

<project>

 <modelVersion>4.0.0</modelVersion>

  <repositories>

    <repository>

      <id>central</id>

      <name>CentralRepository</name>

     <url>https://repo.maven.apache.org/maven2</url>

      <layout>default</layout>

      <snapshots>

        <enabled>false</enabled>

      </snapshots>

    </repository>

  </repositories>

……….

</project>

<!-- END SNIPPET:superpom -->

说明:包含这段配置的文件是所有Maven项目都会继承的超级POM

1.3.4 私服

私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。

当Maven需要下载构件时,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。

另:一些无法从外部仓库下载到的构件,可以从本地上传到私服上供大家使用,比如一些自己开发的构件。或一些有版权问题而中央仓库没有的第三方构件。

 

注:建好私服是用好Maven十分关键的一步,也就是说使用好Maven则必须要建私服。

1.4 远程仓库的配置

开发的问题:有些时候,某件构件可能无法从默认的Maven“中央仓库”中获取,它们存在于其它的Maven远程仓库

方案1:我们可以手工到该网站上下载,然后上传到Maven的“本地仓库”,然后使用。

这看起来很不方便。

Maven方案:POM.xml文件中配置该远程仓库,maven会自动去该远程仓库中查找构件,功能同Maven的中央仓库一样。

如:我们在pom.xml文件中添加一个JbossMaven远程仓库,供我们下载构件到”本地仓库“

--------------------------------------------------------------------------------------------

<repositories>

<repository>

<id>jboss</id>

<name>JBossRepository</name>

<url>http://repository.jboss.com/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>

--------------------------------------------------------------------------------------------

元素说明:

repositories:该元素里面可以声明一个或多个远程仓库 。

repository:远程仓库声明,一个元素声明一个远程仓库。

Id:仓库的id,它必须是唯一的,尤其注意,Maven自动的中央仓库id为central,如果这里声明的id也为central,则会覆盖原本的中央仓库的配置。

url:仓库的地址,该地址一般基于http协议,即可以在浏览器中打开。

releases:表示是否开启该仓库的发布版本下载支持。这里是enabled为true,表示开启。

snapshots:表示是否开启该仓库的快照版本下载支持。这里是enabled为false,表示关闭,maven不会下载snapshots版本的构件。

layout:default表示仓库的布局是Maven2/3的默认布局。

updatePolicy:值never,always,intervalx,用于配置Maven从远程仓库检查更新的频率真。默认daily

checksumPolicy:配置Maven检查检验和文件的策略。

1.4.1 远程仓库的认证

大部分远程仓库无须认证可以访问,但有时出于安全方问的考虑,我们需要提供认证信息才能访问一些远程仓库。

认证信息不能配置在POM.XML文件,而是必须配置在settings.xml中。

<servers>

<server>

<id>jboss</id>

<username>repo_user</username>

<password>repo_pwd</password>

</server>

</servers>

注:这里的id必须要与pom.xml中配置的远程仓库的id值要一致,这样Maven才能确认,这个认证是用于哪个远程仓库的。这里idjboss,跟我们在pom.xml配置的远程仓库 id一致。

1.4.2 部署至远程仓库

私服一大作用是部署第三方构件,包括组织内部生成的构件以及一些无法从外部仓库直接获取的构件。

Maven可以将项目生成的构建部署到指定的仓库中。

在POM.XML中配置用于部署的私服:

1.现在nexus私服如下

 

其中Releases仓库用来放”稳定版本“的构件。

而Snapshots仓库用来放”快照版本“的构件。

2.项目的 pom.xml配置如下:

-----------------------------------------------------------------------

<distributionManagement>

        <repository>

            <id>releases</id>

            <name>public</name>

            <url>http://192.168.10.100:8080/nexus2/content/repositories/releases/</url>

        </repository>

        <snapshotRepository>

            <id>snapshots</id>

            <name>Snapshots</name>

            <url>http://192.168.10.100:8080/nexus2/content/repositories/snapshots/</url>

        </snapshotRepository>

</distributionManagement>

-----------------------------------------------------------------------

注:如果nexus设置的认证,则上传构件,需要在settings.xml中配置认证信息,不管是”下载“还是”上传“配置认证的方式都相同。

------------------------------------------------------------------------

<servers>

<server>

<id>releases</id>

<username>releases_user</username>

<password>releases_pwd</password>

</server>

</servers>

------------------------------------------------------------------------

配置正确后,执行:mvn clean deploy

Maven会将项目构建输出的构件部署到配置对应的远程仓库,如果项目当前的版本是快照版本,则部署到快照版本仓库地址,否则就部署到发布版本仓库地址。

[INFO] Scanning forprojects…

[INFO]                                                                        

[INFO]------------------------------------------------------------------------

[INFO] BuildingAccount Service 1.0.0-SNAPSHOT

[INFO]------------------------------------------------------------------------

[INFO]

[INFO] ---maven-clean-plugin:2.5:clean (default-clean)@ account-service ---

[INFO] DeletingD:\Workspaces\eclipse-jee-oxygen_x86_64\account-service\target

[INFO]

[INFO] ---maven-resources-plugin:2.6:resources(default-resources) @ account-service ---

[INFO] Using 'UTF-8'encoding to copy filtered resources.

[INFO] Copying 2resources

[INFO]

[INFO] ---maven-compiler-plugin:3.1:compile(default-compile) @ account-service ---

[INFO] Changesdetected - recompiling the module!

[WARNING] Fileencoding has not been set, using platform encoding UTF-8, i.e. build isplatform dependent!

[INFO] Compiling 4source files toD:\Workspaces\eclipse-jee-oxygen_x86_64\account-service\target\classes

[INFO]

[INFO] ---maven-resources-plugin:2.6:testResources(default-testResources) @ account-service ---

[INFO] Using 'UTF-8'encoding to copy filtered resources.

[INFO] Copying 1resource

[INFO]

[INFO] ---maven-compiler-plugin:3.1:testCompile(default-testCompile) @ account-service ---

[INFO] Changesdetected - recompiling the module!

[WARNING] Fileencoding has not been set, using platform encoding UTF-8, i.e. build isplatform dependent!

[INFO] Compiling 1source file toD:\Workspaces\eclipse-jee-oxygen_x86_64\account-service\target\test-classes

[INFO]

[INFO] ---maven-surefire-plugin:2.12.4:test(default-test) @ account-service ---

[INFO] Surefirereport directory:D:\Workspaces\eclipse-jee-oxygen_x86_64\account-service\target\surefire-reports

-------------------------------------------------------

 T E S T S

-------------------------------------------------------

Runningcom.juvenxu.mvnbook.account.service.AccountServiceTest

Tests run: 1,Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.178 sec

Results :

Tests run: 1,Failures: 0, Errors: 0, Skipped: 0

[INFO]

[INFO] ---maven-jar-plugin:2.4:jar (default-jar) @ account-service ---

[INFO] Building jar:D:\Workspaces\eclipse-jee-oxygen_x86_64\account-service\target\account-service-1.0.0-SNAPSHOT.jar

[INFO]

[INFO] ---maven-install-plugin:2.4:install(default-install) @ account-service ---

[INFO] InstallingD:\Workspaces\eclipse-jee-oxygen_x86_64\account-service\target\account-service-1.0.0-SNAPSHOT.jartoD:\Workspaces\maven_repository\com\juvenxu\mvnbook\account\account-service\1.0.0-SNAPSHOT\account-service-1.0.0-SNAPSHOT.jar

[INFO] InstallingD:\Workspaces\eclipse-jee-oxygen_x86_64\account-service\pom.xml toD:\Workspaces\maven_repository\com\juvenxu\mvnbook\account\account-service\1.0.0-SNAPSHOT\account-service-1.0.0-SNAPSHOT.pom

[INFO]

[INFO] ---maven-deploy-plugin:2.7:deploy(default-deploy) @ account-service ---

[INFO] Downloading: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/maven-metadata.xml

[INFO] Downloaded: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/maven-metadata.xml(792 B at 6.2 KB/sec)

[INFO] Uploading: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/account-service-1.0.0-20171205.142643-4.jar

[INFO] Uploaded: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/account-service-1.0.0-20171205.142643-4.jar(15 KB at 634.8 KB/sec)

[INFO] Uploading: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/account-service-1.0.0-20171205.142643-4.pom

[INFO] Uploaded: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/account-service-1.0.0-20171205.142643-4.pom(2 KB at 58.0 KB/sec)

[INFO] Downloading: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/maven-metadata.xml

[INFO] Downloaded: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/maven-metadata.xml(302 B at 6.1 KB/sec)

[INFO] Uploading: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/maven-metadata.xml

[INFO] Uploaded: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/1.0.0-SNAPSHOT/maven-metadata.xml(792 B at 110.5 KB/sec)

[INFO] Uploading: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/maven-metadata.xml

[INFO] Uploaded: http://192.168.10.100:8080/nexus2/content/repositories/snapshots/com/juvenxu/mvnbook/account/account-service/maven-metadata.xml(302 B at 22.7 KB/sec)

[INFO]------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO]------------------------------------------------------------------------

[INFO] Total time:4.965 s

[INFO] Finished at:2017-12-05T22:26:43+08:00

[INFO] Final Memory:15M/243M

[INFO]------------------------------------------------------------------------

Maven快照机制(SNAPSHOT)

以下引用自https://ayayui.gitbooks.io/tutorialspoint-maven/content/book/maven_snapshots.html

一、场景

一个大型的软件应用通常包含多个模块,并且通常的场景是多个团队开发同一应用的不同模块。举个例子,设想一个团队开发应用的前端,项目为app-ui(app-ui.jar:1.0),而另一个团队开发应用的后台,使用的项目是data-service(data-service.jar:1.0)。

现在可能出现的情况是开发data-service的团队正在进行快节奏的bug修复或者项目改进,并且他们几乎每隔一天就要发布库到远程仓库。

现在如果data-service团队每隔一天上传一个新版本,那么将会出现下面的问题:

data-service团队每次发布更新的代码时都要告知app-ui团队。

app-ui团队需要经常地更新他们pom.xml文件到最新版本。

为了解决这种情况, 快照(SNAPSHOT)的概念派上了用场。

二、什么是快照(SNAPSHOT)?

快照(SNAPSHOT)是一种特殊的版本,指定了某个当前的开发进度的副本。不同于常规的版本,Maven每次构建都会在远程仓库中检查新的快照。

现在data-service团队会每次发布更新代码的快照到仓库中,比如说data-service:1.0-SNAPSHOT来替代旧的快照jar包。

注意:每次更新jar包时,版本好不变,且后缀必须带上-SNAPSHOT。

三、项目快照(Snapshot) VS 版本(Version)

版本(Version)的情况下,如果Maven以前下载过指定的版本文件,比如说data-service:1.0,Maven将不会再从仓库下载新的可用的1.0文件。若要下载更新的代码,data-service的版本需要升到1.1。

快照(Snapshot)的情况下,每次app-ui团队构建他们的项目时,Maven将自动获取最新的快照(data-service:1.0-SNAPSHOT)。

备注:版本(Version)存放在Release发布仓库。快照(Snapshot)存放在Snapshot快照仓库。

注意:版本(Version)的概念,只要不带有-SNAPSHOT的关键字时,都会认为这是一个在Release发布仓库的jar包。其中在Release发布仓库的jar包命名除了具体的版本号之后还可以带上比如:1.0-Release、1.0-rc1等等的字样。

四、原理详解

Maven中的仓库分为两种,Snapshot快照仓库和Release发布仓库。Snapshot快照仓库用于保存开发过程中的不稳定版本,Release正式仓库则是用来保存稳定的发行版本。定义一个组件/模块为快照版本,只需要在pom.xml文件中在该模块的版本号后加上-SNAPSHOT即可(注意这里必须是大写),如下所示:

<groupId>com.jsoft.test</groupId>
<artifactId>testcommon</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>

Maven会根据模块的版本号(pom.xml文件中的version)中是否带有-SNAPSHOT来判断是快照版本还是正式版本。如果是快照版本,那么在mvndeploy时会自动发布到快照版本库中,而使用快照版本的模块,在不更改版本号的情况下,直接编译打包时,Maven会自动从镜像服务器上下载最新的快照版本。如果是正式发布版本,那么在mvndeploy时会自动发布到正式版本库中,而使用正式版本的模块,在不更改版本号的情况下,编译打包时如果本地已经存在该版本的模块则不会主动去镜像服务器上下载。

所以,我们在开发阶段,可以将公用库的版本设置为快照版本,而被依赖组件则引用快照版本进行开发,在公用库的快照版本更新后,我们也不需要修改pom.xml文件提示版本号来下载新的版本,直接Maven执行相关编译、打包命令即可重新下载最新的快照库了,从而也方便了我们进行开发。

虽然,快照的情况下,Maven在日常工作中会自动获取最新的快照,你也可以在任何Maven命令中使用-U参数强制Maven下载最新的快照构建。命令如下:

mvnclean package -U

1.6 从仓库解析依赖的机制

Maven是根据怎样的规则从仓库解析并使用依赖构件的呢?

 当本地仓库没有依赖构件的时候,Maven会自动从远程仓库下载:当依赖版本为快照版本的时候,Maven会自动找到最新的快照。这背后的依赖解析机制可以概括如下:

1)当依赖的范围是system/的时候,Maven直接从本地文件系统解析构件

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

3)在本地仓库不存在相应构件的情况下,如果依赖的版本是显式的发布版本构件,如1.2、2.1-beta-1等,则遍历所有的远程仓库,发现后,下载并解析使用。

4)如果依赖的版本是RELEASE或者LATEST,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/maven-metadata.xml,将其与本地认为的对应元数据合并后,计算出RELEASE或LATEST真实的值,然后基于这个真实的值检查本地和远程仓库。如步骤2)3)

5)如果依赖的版本是SNAPSHOT,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/maven-metadata.xml,将其与本地认为的对应元数据合并后,得到最新快照版本的值,然后基于该值检查本地仓库,或者从远程仓库下载。

6)如果最后解析得到的构件版本是时间戳格式的快照,如1.4.1-20091104.121450-121,则复制其时间戳格式的文件至非时间戳格式,如SNAPSHOT,并使用该非时间戳格式的构件。

  当依赖版本不明晰的时候,如RELEASE、LATEST和SNAPSHOT,Maven就需要基于更新远程仓库的更新策略来检查更新。有一些配置与此有关:首先是<releases><enabled>和<snapshots><enabled>,只有仓库开启了对于发布版本的支持时,才能访问该仓库的发布版本构件信息,对于快照版本也是同理;其次要注意的是<release>和<snapshots>的子元素<updatePolicy>,该元素配置了检查更新的频率,每日检查更新、永远检查更新、从不检查更新、自定义时间间隔检查更新等。最后,用户还可以从命令行加入参数-U,强制检查更新,使用参数后,Maven就会忽略<updatePolicy>的配置。

 当Maven检查完更新策略,并决定检查依赖更新的时候,就需要检查仓库元数据maven-metadata.xml。

汪:仓库元数据并不是永远正确的,有时候当用户发现无法解析某些构件,或者解析得到错误构件的时候,就有可能是出现了仓库元数据错误,这时就需要手工地,或者使用工具(如Nexus)对其进行修复。

For example:

[root@localhost account-captcha]# ll

total 20

drwxr-xr-x.2 root root 4096 Nov 23 22:49 1.0.0-SNAPSHOT

drwxr-xr-x.2 root root 4096 Dec  6 21:311.0.1-SNAPSHOT

-rw-r--r--.1 root root  342 Dec  6 21:31 maven-metadata.xml

-rw-r--r--.1 root root   32 Dec  6 21:31 maven-metadata.xml.md5

-rw-r--r--.1 root root   40 Dec  6 21:31 maven-metadata.xml.sha1

[root@localhost account-captcha]# catmaven-metadata.xml

------------------------------------------------------

<?xmlversion="1.0" encoding="UTF-8"?>

<metadata>

 <groupId>com.juvenxu.mvnbook.account</groupId>

 <artifactId>account-captcha</artifactId>

  <versioning>

    <versions>

     <version>1.0.0-SNAPSHOT</version>

     <version>1.0.1-SNAPSHOT</version>

    </versions>

    <lastUpdated>20171206133106</lastUpdated>

  </versioning>

</metadata>

------------------------------------------------------

/app/nexus/storage/snapshots/com/juvenxu/mvnbook/account/account-captcha/1.0.0-SNAPSHOT

[root@localhost 1.0.0-SNAPSHOT]# catmaven-metadata.xml

------------------------------------------------------

<?xmlversion="1.0" encoding="UTF-8"?>

<metadatamodelVersion="1.1.0">

 <groupId>com.juvenxu.mvnbook.account</groupId>

 <artifactId>account-captcha</artifactId>

  <version>1.0.0-SNAPSHOT</version>

  <versioning>

    <snapshot>

     <timestamp>20171123.144949</timestamp>

      <buildNumber>3</buildNumber>

    </snapshot>

   <lastUpdated>20171123144949</lastUpdated>

    <snapshotVersions>

      <snapshotVersion>

        <extension>jar</extension>

       <value>1.0.0-20171123.144949-3</value>

       <updated>20171123144949</updated>

      </snapshotVersion>

      <snapshotVersion>

        <extension>pom</extension>

       <value>1.0.0-20171123.144949-3</value>

       <updated>20171123144949</updated>

      </snapshotVersion>

    </snapshotVersions>

  </versioning>

</metadata>

------------------------------------------------------

[root@localhost 1.0.1-SNAPSHOT]# catmaven-metadata.xml

------------------------------------------------------

<?xmlversion="1.0" encoding="UTF-8"?>

<metadatamodelVersion="1.1.0">

 <groupId>com.juvenxu.mvnbook.account</groupId>

 <artifactId>account-captcha</artifactId>

  <version>1.0.1-SNAPSHOT</version>

  <versioning>

    <snapshot>

      <timestamp>20171206.133106</timestamp>

      <buildNumber>1</buildNumber>

    </snapshot>

   <lastUpdated>20171206133106</lastUpdated>

    <snapshotVersions>

      <snapshotVersion>

        <extension>jar</extension>

       <value>1.0.1-20171206.133106-1</value>

       <updated>20171206133106</updated>

      </snapshotVersion>

      <snapshotVersion>

        <extension>pom</extension>

       <value>1.0.1-20171206.133106-1</value>

       <updated>20171206133106</updated>

      </snapshotVersion>

    </snapshotVersions>

  </versioning>

</metadata>

------------------------------------------------------

1.7 镜像

如果仓库X可以提供仓库Y存储的所有内容,则X是Y的一个镜像。换句话说,任何一个可以从仓库Y获得的构件,都可以从它的镜像中获取。

如:http://maven.net.cn/content/groups/public

是中央仓库 http://repo1.maven.org/maven2 在中国的镜像。

在中国,该镜像的速度比中央仓库访问的速度要快。

我闪可以配置Maven使用该镜像来替代中央仓库。

修改setttings.xml文件:

<mirrors>
    <mirror>
         <id>maven.oschina.net</id>
         <name>mavenmirror in China</name>
         <url>http://maven.oschina.net/content/groups/public/</url>
         <mirrorOf>central</mirrorOf>
    </mirror>
</mirrors>

该例中,mirrorOf的值为central,表示该配置为中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像,用户也可以使用同样的方法配置其他仓库的镜像。id表示镜像的唯一标识符,name表示镜像的名称,url表示镜像的地址。

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

For example:

这我们有一个私服,我们使用默认的仓库组public repositories,它管理了Releases,Snapshots, 3rd party, Central几个仓库。

我们用这个仓库组对外开放。

http://192.168.10.100:8080/nexus2/content/groups/public/

 

<!--配置私服镜像-->
<mirrors>
    <mirror> 
         <id>nexus</id> 
         <name>internal nexus repository</name> 
         <url>http://192.168.10.100:8080/nexus2/content/groups/public/</url> 
         <mirrorOf>*</mirrorOf> 
     </mirror> 
 </mirrors>

该例中<mirrorOf>的值为星号,表示该配置是所有Maven仓库的镜像,任何对于远程仓库的请求都会被转至http://183.238.2.182:8081/nexus/content/groups/public/。

如果该镜像仓库需要认证,则配置一个id为nexus的认证信息即可。

镜像高级的配置:

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

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

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

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

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

可用的Maven镜像仓库

      <mirror>   
        <id>repo2</id>   
       <mirrorOf>central</mirrorOf>   
        <name>HumanReadable Name for this Mirror.</name>   
        <url>http://repo2.maven.org/maven2/</url>   
      </mirror>
 
      <mirror>   
        <id>ui</id>   
       <mirrorOf>central</mirrorOf>   
       <name>HumanReadable Name for this Mirror.</name>   
     <url>http://uk.maven.org/maven2/</url>   
     </mirror>

     <mirror>   
       <id>ibiblio</id>   
       <mirrorOf>central</mirrorOf>   
       <name>HumanReadable Name for this Mirror.</name>   
      <url>http://mirrors.ibiblio.org/pub/mirrors/maven2/</url>   
     </mirror>

    <mirror>   
       <id>jboss-public-repository-group</id>   
       <mirrorOf>central</mirrorOf>   
      <name>JBossPublic Repository Group</name>   
      <url>http://repository.jboss.org/nexus/content/groups/public</url>   
     </mirror>
 
     <mirror>   
       <id>JBossJBPM</id>  
 <mirrorOf>central</mirrorOf>  
 <name>JBossJBPMRepository</name>  
 <url>https://repository.jboss.org/nexus/content/repositories/releases/</url> 
 </mirror>

上面的仓库经过测试是可以访问的。

仓库搜索服务地址

问题1:在我们Maven中常开发时,我们经常需要寻找需要依赖,但添加Maven依赖需要我们提供Maven坐标。但坐标太难记。

方案:我们可以使用仓库搜索服务,通过关键字来得到依赖的Maven坐标。

类似我们百度一下,可以通过关键字来查找需要的东西。

下面有几个网站提供仓库搜索服务:

1.自己建立的nexus私服

http://192.168.10.100:8080/nexus2

 

2.公共nexus服务器

SonatypeNexus:https://repository.sonatype.org/

3.MVNrepository

MVNrepository:http://mvnrepository.com/


猜你喜欢

转载自blog.csdn.net/arnolian/article/details/78837463