maven基础篇(6)-maven仓库

来源:互联网 发布:php soapclient 超时 编辑:程序博客网 时间:2024/04/29 23:06

一,maven仓库

        maven仓库,就是指存放包括依赖,插件和项目等一切maven构件的简单文件系统。特别注意,是文件系统。也就是每一个构件在其中都是以文件的方式存在,并且构件存放的规则是按照maven坐标的方式,一般为groupId/artifactId/version/artifactId-version(-classifier).packaging的方式。按照这样的方式,你可以进入仓库去查找某个依赖看看究竟是不是这样。另外,maven对依赖的解析也是按照maven坐标去构建这个路径去寻找的,这也强调了maven世界,构件的坐标是多么重要。在此,我进入我的本地仓库看看:
        这里写图片描述

        maven仓库共分为两种,本地仓库,远程仓库。而远程仓库又分为私服,中央仓库和其他仓库。上面说过,maven寻找构件是根据maven坐标构建路径去寻找的,首先会进入我们本地的仓库去寻找。如果本地仓库没有,或者需要这个构件更新的版本,则是联网去远程仓库(默认去为中央仓库)寻找。在远程仓库寻找依旧是利用maven坐标构建构件路径来寻找的。如果找到了则下载或更新进本地仓库,反之找不到则报maven错误。
        中央仓库并不包括我们开发所需的全部构件,所以其他仓库比如JBoss Maven库等就是提供补充作用的。这个其他的远程仓库都可以直接进行配置的。另外现在企业开发都会在自己的局域网建立自己私有的仓库服务器,也即私服。建立私服有诸多好处:1,节省外网带宽,不必每次都连外网下载构件;2,加速maven构建,不必每次连接外网(直接在局域网连接私服)更新或下载构件(maven插件更新机制会定时更新);3,部署一些无法在远程仓库部署的第三方构件或者项目输出,供内部项目使用;4,由于连接私服是用的局域网,一方面maven构建更稳定,另一方面很多私服可以进行人为的控制;5,减少中央仓库的高访问负荷。


二,几种仓库

1,本地仓库配置
        本地仓库在没运行maven命令之前并不存在。当第一次运行maven命令时,在windows系统maven会创建本地仓库,默认地址为:C:\Users{你的用户名}\.m2\repository。本地仓库会从远程仓库下载很多的构件,放在系统盘会影响电脑的运行速度等,还有可能系统盘的空间不够大。一般,我们会修改maven默认的本地仓库位置。在此,我把我的本地仓库修改情况如下:
        修改{你的maven解压根目录}\conf\settings.xml,如下:
        这里写图片描述

        特别注意:不建议修改{你的maven解压根目录}\conf\settings.xml这个位置的全局配置文件,因为这个是默认的全局配置文件。如果你修改了这个位置的全局配置文件,并且你的电脑是多个用户使用,这个位置的配置会对别的用户也产生影响。最好的方式,是把{你的maven解压根目录}\conf\settings.xml这个默认位置的全局配置文件复制一份放在别的文件夹下,然后你用IDE集成工具开发时指定使用这个新位置的配置文件。如下:
        这里写图片描述

2,中央仓库
        如下图打开maven的pom-4.0.0.xml,可以看到中央仓库配置为maven的默认远程仓库,。
这里写图片描述
这里写图片描述

        特别注意,这个pom-4.0.0.xml是超级pom,你项目中的所有pom都会继承这个pom。这个超级pom描述了构建maven项目的基本情况以及必须插件,这也是为什么你在你的pom中不做任何配置(除了项目坐标)都可以自动生成一个maven项目的原因。更详细的情况,在以后学习时再做总结。如下:

<?xml version="1.0" encoding="UTF-8"?><project>  <modelVersion>4.0.0</modelVersion>  <repositories>    <repository>      <id>central</id>      <name>Central Repository</name>      <url>https://repo.maven.apache.org/maven2</url>      <layout>default</layout>      <snapshots>        <enabled>false</enabled>      </snapshots>    </repository>  </repositories>  <pluginRepositories>    <pluginRepository>      <id>central</id>      <name>Central Repository</name>      <url>https://repo.maven.apache.org/maven2</url>      <layout>default</layout>      <snapshots>        <enabled>false</enabled>      </snapshots>      <releases>        <updatePolicy>never</updatePolicy>      </releases>    </pluginRepository>  </pluginRepositories>  <build>    <directory>${project.basedir}/target</directory><!--maven构建的一系列情况 -->    <outputDirectory>${project.build.directory}/classes</outputDirectory>    <finalName>${project.artifactId}-${project.version}</finalName>    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>    <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>    <resources>      <resource>        <directory>${project.basedir}/src/main/resources</directory>      </resource>    </resources>    <testResources>      <testResource>        <directory>${project.basedir}/src/test/resources</directory>      </testResource>    </testResources>    <pluginManagement>      <plugins>        <plugin><!--maven ant插件 -->          <artifactId>maven-antrun-plugin</artifactId>          <version>1.3</version>        </plugin>        <plugin><!--maven装配插件 -->          <artifactId>maven-assembly-plugin</artifactId>          <version>2.2-beta-5</version>        </plugin>        <plugin><!--maven依赖插件 -->          <artifactId>maven-dependency-plugin</artifactId>          <version>2.8</version>        </plugin>        <plugin><!--maven发布插件 -->          <artifactId>maven-release-plugin</artifactId>          <version>2.3.2</version>        </plugin>      </plugins>    </pluginManagement>  </build>  <reporting>    <outputDirectory>${project.build.directory}/site</outputDirectory>  </reporting>  <profiles>    <profile>      <id>release-profile</id>      <activation>        <property>          <name>performRelease</name>          <value>true</value>        </property>      </activation>      <build>        <plugins>          <plugin><!--maven源码打包插件 -->            <inherited>true</inherited>            <artifactId>maven-source-plugin</artifactId>            <executions>              <execution>                <id>attach-sources</id>                <goals>                  <goal>jar</goal>                </goals>              </execution>            </executions>          </plugin>          <plugin><!--maven文档插件 -->            <inherited>true</inherited>            <artifactId>maven-javadoc-plugin</artifactId>            <executions>              <execution>                <id>attach-javadocs</id>                <goals>                  <goal>jar</goal>                </goals>              </execution>            </executions>          </plugin>          <plugin><!--maven部署插件 -->            <inherited>true</inherited>            <artifactId>maven-deploy-plugin</artifactId>            <configuration>              <updateReleaseInfo>true</updateReleaseInfo>            </configuration>          </plugin>        </plugins>      </build>    </profile>  </profiles></project>

3,私服
        在局域网上搭建私服,对外网的远程仓库进行代理。那么当maven在本地仓库找不到时,就会先到私服上去找。如果私服上没有那个构件,则再转到外网的远程仓库上去找。找到后先下载缓存进私服,再对maven本地项目提供下载服务。本地的项目输出也可以部署到私服上。借用书上的一张图:
        这里写图片描述


三,远程其他仓库的配置

        中央仓库并没有包括全部的构件,有时我们的项目所需的一些构件来源于第三方maven库,那么我们就需要对其他远程仓库(包括Jboss maven库等的其他远程仓库和私服)进行配置。

1,远程其他仓库的配置和认证
        在本地项目的pom.xml中进行其他仓库的配置,这里以配置jboss maven库为例,如下:

<repositories>        <repository><!-- 配置JBoss maven仓库 -->            <id>jboss</id><!-- maven仓库id,必须是唯一的 -->            <name>JBoss Repository</name><!-- 仓库名 -->            <url>http://repository.jboss.com/maven2</url><!--远程仓库地址  -->            <releases><!-- 发布版本构件的支持配置 -->                <enabled>true</enabled>            </releases>            <snapshots><!-- 快照版本构件的支持配置 -->                <enabled>true</enabled>                <updatePolicy>daily</updatePolicy><!-- 快照版本更新周期 -->                <checksumPolicy>ignore</checksumPolicy><!--maven检查检验文件的策略  -->            </snapshots>        </repository>   </repositories>

        如上面注释,id应该是唯一的,不应该和别的远程仓库id相同。假如这里的id改成中央仓库的id,那么这个jboss仓库就会覆盖掉中央仓库。前面已经浅显的提到过,配置了 中央仓库的maven超级pom会被当前项目的pom继承,如果id相同的仓库配置子pom则会覆盖父pom。url指定了配置的远程仓库的地址。releases指定的是本项目对远程仓库发布版本构件的下载支持配置情况。snapshots指定的是本项目对远程仓库快照版本构件的下载支持配置。snapshots和releases都有enabled,updatePolicy和checksumPolicy这三个子元素。enabled指定对某种版本构件下载是否支持。updatePolicy指定的是本项目中下载的这个远程仓库的构件从远程仓库的更新周期。每个构件在被部署到仓库时,都会同时部署对应的校验文件,checksumPolicy指定当本地项目从远程仓库下载构件时的校验策略,其中ignore指完全忽略校验和错误。

        已经配置了其他远程仓库,一般这样我们就可以访问这个远程仓库了。但是有时候出于安全考虑,有些远程仓库或者我们自己搭建的私服是需要输入用户名和密码这些认证消息才能够访问的。那么我们在本地怎么配置认证消息呢?《Maven实战》上说这个认证配置信息一般放在settings.xml而不是配置在pom.xml中,因为pom会被提交到代码库供所有成员访问。这个解释其实我是真的不理解的,现在只是在学maven并没有多少利用maven开发的经验。所以,请明白的告诉我,可好? 凭借我某次和别人一起开发的经验,我还是要强行解释一波,如果有错,请指教!很多时候,一些企业项目都是团队一起开发,用svn等进行版本控制,我们通常是把项目分很多模块给每个人开发,开发的过程会经常上传自己的代码和从服务器下载更新自己的代码。那么这个项目中的代码和pom.xml是大家共享的,谁都有可能会去修改pom.xml中的一些配置。所以是不是因为这个会不安全,会当我更新时影响我对我在pom.xml配置的远程仓库的访问?修改本地我的maven中的settings.xml只有我自己独享,这样更安全。我只能这样理解啦,望指教!!!在settings.xml配置远程服务器认证情况如下:
这里写图片描述

        特别注意,在pom.xml配置的远程服务器id一定要和在settings.xml中配置的远程服务器认证消息id一样!!!不然,你懂的,相当于没有对那个需要认证的远程服务器配置验证消息。

2,把项目或第三方构件部署到私服

        其他远程服务器的配置和认证上文都已经学了,这里再配置私服和认证私服应该就都会了吧。我们也经常把我们的项目输出和一些中央仓库或者其他远程仓库没有的构件部署到私服,供我们所有项目组成员使用。我们可以利用maven的一个命令mvn clean deploy把我们的项目输出部署到私服的发布版本仓库或者快照版本仓库,具体发布到哪种仓库是根据我们在当前项目的pom.xml中配置的项目坐标中的version决定的。但是前提我们必须得在pom.xml做一些配置,因为运用这个maven命令,maven会去当前项目 的pom.xml读取部署的位置。如果不对私服进行部署配置,那么maven就会根据超级pom-4.0.0.xml默认部署到本地指定文件夹。当前项目的pom.xml配置部署私服的实例如下,其中的一些配置说明已在代码中注释。

   <distributionManagement><!-- 发布部署配置 -->        <repository><!-- 私服-发布版本仓库 -->            <id>proj-releases</id><!-- 仓库id -->            <name>Proj Release Repository</name> <!-- 仓库名 -->            <url>http://192.168.1.100/content/repositories/proj-releases</url><!-- 发布版本地址 -->        </repository>        <snapshotRepository><!-- 快照版本仓库 -->            <id>proj-snapshots</id><!-- 仓库id -->            <name>Proj Snapshot Repository</name> <!-- 仓库名 -->            <url>http://192.168.1.100/content/repositories/proj-snapshots</url><!-- 快照版本地址 -->        </snapshotRepository>   </distributionManagement>

3,“快照版本”的理解

        构件的版本,分为发布版本和快照版本等。发布版本,表示稳定版本,对这个版本不会再做修改或变动。举例,发布版本的命名一般为1.0,2.0.0或3.1-alpha-2这样的。总之发布版本的名字中不含时间的成分。而快照版本则为不稳定版本,很有可能还在修改中或者未完成中。快照版本的命名一般为2.1-SNAPSHOT或者2.1-20191109.221412-13这样的。即快照版本一般命名中含SNAPSHOT或者具体时间和快照次数(例如,20191109.221412-13)。
        加入这个快照版本的概念,旨在保证项目开发过程中从仓库获得的不稳定构件为最新版本的构件。当我们把例如2.1-SNAPSHOT版本的这个构件部署到私服仓库时,maven会自动把2.1-SNAPSHOT中的SNAPSHOT换成时间(和次数)。也因此,我们能够通过这个时间来判断版本的新旧。而当我们再用version为2.1-SNAPSHOT的这个构件坐标从私服下载这个构件时,maven也会通过判断很多版本的这个构件名字中的时间去寻找并下载这个最新版本的构件。要特别注意:1,当构件经过完善测试需要发布后,要把其版本改为稳定版本;2,最好不要使用外部的快照版本,由于快照版本的不稳定,可能会影响你正在开发的项目。


四,从仓库解析依赖的机制

这里写图片描述

        先来理解一下maven的元数据metadata,它在maven中的表现是maven-metadata(-xxx).xml。我们从三个方面来理解maven元数据:

  1. 关于快照版本snapshot的构件,maven会为为它维护一个maven-metadata(-xxx).xml,这里面记录了构件的详细信息。其中一个主要目的是记录maven在install 或 deploy这个构件时的具体时间(和次数)。来看一个例子:

    我在eclipse中创建了一个maven项目demo1,如图:
    这里写图片描述

    现在我第一次执行install,把demo1打包安装进我的本地maven仓库,如图:
    这里写图片描述
    这里写图片描述
    我的仓库多了一个构件,也就是这个demo1项目打包的jar,如图:
    这里写图片描述
    打开maven-metadata-local.xml看一下,特别注意其中lastUpdated和updated这个具体的时间,如图:
    这里写图片描述
    第二次执行install。执行完后,再次打开maven-metadata-local.xml看一看,这次lastUpdated和updated这个具体的时间变成了第二次执行install的时间。如图:
    这里写图片描述
    特别注意:maven在利用名字中带有snapshot的这个版本号来解析这个构件时,会利用这个元数据文件maven-metadata-local.xml,查找其中最新更新时间,并把snapshot换成最新的更新时间(和次数)返回给用户。

  2. mave2,对就是maven2中还有一个特殊的构件版本latest。我反复修改demo1中的项目版本,并且进行install操作,就是没发现元数据中有latest,经过百度发现maven3已经去除了这个,那么在这里则不理会这个latest啦。我不会去使用maven2,但是maven3没有这个latest并不影响学习maven-metadata-local.xml。打开仓库中查看,如图仓库中维护了很多版本的这个构件。在打开元数据文件,发现这个文件versions里面记录了所有的历史版本和release中记录了最新的发布版本。
    这里写图片描述
    这里写图片描述
    特别注意:当把这个项目构件部署到私服时,当别的项目需要这个项目构件,那么从私服上解析这个构件同样需要通过读取这个元数据文件来判断需要的版本的这个构件是否存在。
  3. 如果要运行某个插件的goal,只要指定插件的 prefix 和 goal 名称就能正确调用你想使用的插件的goal,形如在命令行使用:mvn dependency:tree 和IDE中使用:dependency:tree 。那么这是如何做到的呢?maven去仓库中寻找正确的插件也是通过goupId,artifactId和version这几个坐标元素去寻找的。那么当运行prefix:goal这样的命令时,是如何找到插件并执行插件目标的呢?想一下,肯定存在从prefix到插件的映射,那么这个映射则默认记录在org.apache.maven.plugins文件夹下的很多元素据mave-metadata(-xxx).xml文件中。那么maven如何找到org.apache.maven.plugins文件夹并从中寻找那些元数据文件呢?这个简单,肯定是记录在源码中(这个我还没找到源码,谁找到麻烦留言告诉我)。具体的插件解析过程,请参考《maven插件解析机制》,这里不细讲。那我们现在来打开org.apache.maven.plugins下的一个元数据文件,里面有很多plugin,并且每一个prefix映射一个具体的插件,如下:
    这里写图片描述


        关于maven metadata就总结这些吧。那么本章最上面从仓库解析依赖的图中最难理解的部分则是本地仓库和远程仓库的元数据合并并计算release和snapshot的真实值(因为maven3去除了,这里则不再提latest),这部分是不是容易理解一点了呢。合并后的构件元数据信息,可以很容易找到release和snapshot最新版本的version的值。再通过这个值去本地仓库查找,找不到再到远程仓库查到。


五,仓库镜像

        任何一个从X仓库可以获得构件,在Y中也可以获得,那么Y仓库则为X仓库的镜像。通常在settings.xml中配置maven对某个仓库镜像的访问。特别注意,如果镜像仓库出现问题,那么镜像仓库相关的所有被镜像仓库也将无法访问。如下图,配置了central中央仓库的镜像,那么对中央仓库的访问都将转向访问配置的镜像仓库。
        这里写图片描述
        配置在局域网的私服,可以代理外网的远程仓库。所以把私服在settings.xml设置为其他所有远程仓库的镜像,所有的一切向远程仓库下载构件的需要都将转向从私服下载。如果私服没有,那么私服则会把下载请求转向外网的远程仓库,找到构件后缓存进私服,再供本地去下载。这也符合一切从所有远程仓库获得的构件,都可以从私服直接或者间接获得。那么,私服也便成为别的远程仓库的一种镜像。在settings.xml配置私服镜像情况如下:
        这里写图片描述
        如上图实例,对所有远程仓库的访问都将转向访问私服。其中特别指出mirrorOf配置的是对哪种仓库配置镜像。可以配置的值的类型有以下几种,1,[*]:匹配所有远程仓库;2,[rep1,rep2]:匹配这两个远程仓库;3,[*,!rep1]:匹配除rep1外的所有远程仓库;4,[external:*]:匹配所有不在本机的所有远程仓库。


个人声明:这篇博文是自己学习《Maven实战》和一些博文,根据自己理解总结所写。由于理解和专业素养有限,若发现错误,请纠正,谢谢!!!


参考资料:
1,《maven metadata 解析》
2,《maven插件解析机制》
3,《How do I tell Maven to use the latest version of a dependency?》
4,《Maven实战》

0 0
原创粉丝点击