Maven学习笔记(十一)Maven仓库

Maven仓库

    坐标和依赖是任何一个构件在Maven世界中的逻辑表示方式,而构建的物理表方式是文件,Maven通过仓库来统一管理这些文件。
什么是Maven仓库
    在Maven的世界中,任何一个依赖、插件或者项目构建的输出,都可以称为构件。在之前的account-email大家可以看到POM中生命力了很多依赖还有插件,这些都是构件的一种。

    在实际项目中,经常一台工作站上可能会有几十个项目,很多的项目中我们可以发现有一个叫做lib的目录,该目录下存放了大量的类库文件,而很多的类库文件其实是重复性的。比如两个使用springframework框架的web项目,那么必然springframework的相关类库是重复的,这样做不仅造成了磁盘空间的浪费,而且也难于统一管理,文件的复制操作也会降低构建的速度。

    但是如果使用Maven的话,就可以很好的避免这些问题,这些都得益于坐标机制。任何Maven的项目使用任何一个构件的方式都是完全相同的。在此基础上,Maven可以在某个位置存放统一存储所有Maven项目共享的构件,这个统一的位置就是Maven的仓库。实际的Maven项目不再各自存储依赖文件,它们只需要声明这些依赖的坐标,在需要的时候,Maven会自动的根据坐标找到仓库中的构件,并使用它们。

    在下图中大家可以轻易的看到,构件存储的位置,是在我本机的Maven本地仓库中,而不是在项目路径下:

这里写图片描述

仓库的布局
    任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中唯一存储路径,这便是Maven的仓库布局方式。例如上图中Junit-4.7.jar大家可以发现,其对应的Maven 的仓库路径为:
        D:\apache-maven-3.2.5-bin\repository\junit\junit\4.7\junit-4.7.jar
    该路径与坐标的对应关系为:
        groupId\artifactId\version\artifact-version.packaging
    从上面我们可以看到,Maven仓库是基于简单文件系统存储的,因此当遇到些与仓库相关的问题时,可以很方便的查找相关文件,方便定位问题。
仓库的分类
    对于Maven来说,仓库只有两类:本地仓库和远程仓库。当Maven根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在构件,则直接使用,如果本地仓库没有,或者需要查看是否有更新的构件版本,Maven就会去远程仓库查找,发现需要的构件后,就会下载到本地仓库,然后再使用。

    如果本地仓库和远程仓库都没有该构件,Maven就会报错。

    Maven的远程仓库中有一个最重要的仓库,叫做中央仓库。该仓库是Maven核心自带的远程仓库,它包含了绝大部分开源的构件。在默认的配置下,当本地仓库没有Maven需要的构件时,它就会尝试从中央仓库下载。

    而私服是另一种特殊的远程仓库,在实际项目中,公司为了节省带宽和时间,往往会假设一个私有的仓库服务器,用它来代理所有的外部的远程仓库。内部的项目还能部署到私服上供其他项目的使用。

这里写图片描述

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

    默认情况下,不管是Windows还是Linux上,每个用户在自己的用户目录下都有一个路径名为.m2\repository\的仓库目录。当然在Linux目录中,以“.”开头的目录和文件是隐藏的,想要查看需要使用 ls -a命令。

    如果想要自定义本地仓库目录地址,可以编辑.m2\settings.xml文件,设置localRepository元素的值为想要的仓库地址,例如本人便将Maven的仓库移到了Maven的安装目录下,便于管理。

这里写图片描述

    但是这里要注意一个问题,默认情况下,.m2\settings.xml文件是不存在的,需要从Maven安装目录复制$M2_HOME\conf\settings.xml文件再进行编辑。

    构件只有安装在本地仓库中,才可以供其他Maven项目使用,一般来说,依赖是由Maven从远程仓库下载到本地仓库中,再供项目使用,但是有些公司内部开发的框架,工具包,是在远程仓库中找不到的,因此就需要安装到Maven仓库中,在项目根目录执行以下命令安装项目到Maven 的本机仓库中:
        mvn clean install
    执行后效果如下:

这里写图片描述

    Install插件的install目标将项目的构建输出文件安装到本地仓库。
远程仓库
    安装好Maven后,如果不执行任何命令,本地仓库是不存在的。当用户输入第一条命令之后,Maven才会创建本地仓库,然后根据配置和需要从远程仓库下载构件到本地仓库。

    当Maven无法从本地仓库获取构件的时候,就会从远程仓库下载至本地仓库。

    一般地,对于每个人来说,书房只有一个,但外面的书店很多,类似的,对于Maven来说,每个用户只有一个本地仓库,但是可以配置很多远程仓库。
中央仓库
    由于最原始的本地仓库是空的,Maven必须知道至少一个可用的远程仓库,才能在Maven执行命令的时候下载到需要的构件。

    中央仓库就是这样一个默认的仓库,Maven的安装文件中自带了中央仓库的配置,我们可以解压如下文件,查看到中央仓库的配置:
        D:\apache-maven-3.2.5-bin\apache-maven-3.2.5\lib\maven-model-builder-3.2.5.jar
    在该jar包的如下路径可以找到POM文件:
        D:\apache-maven-3.2.5-bin\apache-maven-3.2.5\lib\maven-model-builder-3.2.5\org\apache\maven\model\pom-4.0.0.xml
    打开后,可以找到如下配置中央仓库的代码片段:

这里写图片描述

    包含这段配置的文件是所有Maven项目都会继承的超级POM,这段配置使用id central对中央仓库进行唯一标识。其名称为Central Repository ,它使用default仓库布局。也就是简单文件系统的仓库布局。最后需要注意的是snapshots元素,其子元素enabled指定的值为false,表示不从该中央仓库下载快照版本的构件,也就是不稳定版本的构件。

    由于中央仓库包含了超过2000个开源项目的构件,因此一般来说,一个简单Maven项目所需要的依赖构件都能从中央仓库下载到。
私服
    私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。此外一些无法从外部仓库下载的构件,也可以从本地上传到私服上供以使用。如下图所示:

这里写图片描述

           节省自己的外网带宽。比如有100个Maven用户需要缓存构件,其中有大量的重复构件,如果不使用私服,那么就会从远程仓库下载100次大量的构件,但是如果使用私服后,由私服缓存远程仓库的构件,再由用户从私服上取得构件,那么大量重复的构件,就不需要重复性的下载多次,只需要私服一次从远程仓库缓存下载即可。节省的带宽资源可以想象。

           加速Maven的构建。这一点不用说,局域网之间访问的速度必然大于广域网的访问速度。

           部署第三方控件。当公司内部有一套自己的框架或者构件的时候,安装到私服上供大家使用是最方便的。

           提高稳定性,增强控制。Maven构建高度依赖远程仓库,当广域网连接不稳定的时候,如果不使用私服,这是一件非常让人崩溃的事情。

           降低中央仓库的负荷。建立私服后,重复性构件的下载只需要一次即可,大大降低了中央仓库的访问次数,如果大家都使用私服,可以想象能够降低中央仓库多少的负荷。
远程仓库的配置
    如果默认的中央仓库无法满足项目的需求,那么我们可能会配置其他的远程仓库如JBoss Maven仓库。这时可以在POM中配置该仓库。

这里写图片描述

    需要注意的是,Maven配置远程仓库是,ID元素的值必须是唯一的,否则会覆盖同名的仓库。另外需要注意的是releases元素为true表示下载发布版本的构件,snapshots元素为false,表示不下载快照版本的构件。

另外对于releases和snapshots来说,还有两个子元素如下:

这里写图片描述

    元素updatePolicy用来配置Maven从远程仓库检查更新的频率。默认的值为daily,表示Maven会每天检查一次。其它值为:never-从不检查更新,always-每次构建都检查更新,interval-X每隔X分钟检查一次更新,X为任意数。

    元素checksumPolicy用来配置Maven检查检验和文件的策略。当构件被部署到Maven仓库中时,会同时部署对应的校验和文件。在下载构件的时候,Maven会验证校验和文件,如果校验和验证失败时,当checksumPolicy的值为默认的warn时,Maven会在执行构建时输出警告信息,其他可用的值为:fail-Maven遇到校验和错误就让构建失败,ignore-使Maven完全忽略校验和错误。
远程仓库的认证
    大部分远程仓库无须认证就可以访问,但也有一些需要认证才可以访问。例如组织内部的Maven仓库服务器,为了防止非法的仓库访问,管理员为每个仓库提供了一组用户名及密码。这时访问就需要配置认证信息。

    配置认证信息和配置仓库信息不同,仓库信息可以直接配置在POM文件中,但是认证信息必须配置在settings.xml文件中。这是因为POM往往是被提交到代码仓库中供所有成员访问的。而settings.xml文件是一直存放在本机的。因此在settings.xml文件中配置认证信息更加的安全。

    配置方式如下所示:

这里写图片描述

    Maven使用settings.xml文件中并不显而易见的servers元素及其子server元素配置仓库认证信息。settings.xml中server元素的id必须与POM中需要认证的repository元素的id完全一致,正是这个id,将认证信息与仓库配置联系在了一起。
部署至远程仓库
    之前说过,私服的一大作用就是部署第三方构件,包括组织内部生成的构件及无法在远程仓库获取的构件。

    Maven除了能对项目进行编译,测试,打包之外,还能将项目生成的构件部署到仓库中。首先需要编辑项目的pom.xml文件。配置distributionManagement元素如下:

这里写图片描述

    上面部分配置了远程仓库和远程快照仓库的信息,这两个仓库都配置了id,name和url,id作为仓库的唯一标识,name是为了方便人阅读,url表示该仓库的地址。

    在向远程仓库部署构件的时候,往往需要认证信息,因此之前配置的server元素,就起到了至关重要的作用。

    不管是从远程仓库下载构件还是部署构件,认证配置的方式是一样。

    配置正确后,在命令行执行如下命令即可部署:
        mvn clean deploy 
    注意:该命令,本人目前未做试验,主要是没有私服,后面会有架设私服的内容,在私服架设后,本人会验证该命令,并上传结果图,请见谅。
快照版本
    Maven为什么要区分快照版本和发布版本呢?

    其实是为了更好协作模块开发,书中提了一个例子非常的形象,内容如下:

    小张在开发模块A的2.1版本,该版本还未正式发布,与模块A一起开发的还有模块B,它由小张的同事季MM开发,B功能依赖于A,在开发的过程中,小张需要经常将自己最新的构建输出,交给季MM,供她开发和集成调试,问题是,这个工作如何进行呢?

    方案A:

        让季MM自己签出模块A的源码进行构建。这种方法能确保季MM得到模块A的新构件,不过她不得不去构建模块A。多了一些版本控制和Maven操作不算,当构建失败的时候,她会是一头雾水,最后不得不找小张解决。显然这种方法非常低效。

    方案B:

        重复部署模块A的2.1版本供季MM下载。虽然小张能够保证仓库中的构件是最新的,但对于Maven来说,同样的版本和同样的坐标就意味着同样的构件,因此如果季MM在本机的本地仓库包含了模块A的2.1版本构件,Maven就不会再对照远程仓库进行更新。除非她每次执行Maven命令前,清楚本地仓库。但这种要求手工干预的做饭显然也是不可取的。

    方案C:

        不停的更新版本2.1.1、2.1.2、2.1.3……。首先小张和季MM两个人都需要频繁的更改POM,如果更多的模块依赖模块A,就会涉及更多的POM更改;其次大量的版本其实仅仅包含了微小的差异,有时候是对版本号的滥用。

    Maven 的快照版本就是为了解决如上的问题,在上述的例子中,小张只需要将Maven模块A的版本设定为2.1-SNAPSHOT,然后发布到私服中,在发布的过程中Maven会自动为构件打上时间戳。有了该时间戳,Maven就能随时找到仓库中该构件2.1-SNAPSHOT版本最新的文件。这时,季MM配置对于模块A的2.1-SNAPSHOT版本的依赖,当她构件模块B的时候,Maven会自动从仓库检查模块A的2.1-SNAPSHOT的最新构件,当发现有更新时便进行下载。默认情况下Maven每天检查一次更新。由仓库配置的updatePolicy控制。用户可以使用命令行参数 -U强制Maven检查更新,比如如下命令:
        mvn clean install-U
    快照版本,只应该在组织内部的项目或模块间依赖使用,因为这时,组织对于这些快照版本的依赖有完全的理解及控制权,项目不应该依赖于任何组织外部的快照版本依赖,由于快照版本的不稳定性,这样容易造成隐患。
镜像
    如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。也就是说任何一个可以从仓库Y获得的构件,都能够从它的镜像中获取。比如说地址:http://maven.net.cn/content/groups/public 是中央仓库在中国的镜像,由于地理位置的因此,该镜像往往能够提供比中央仓库更快的服务。因此可以配置Maven使用该镜像来替代中央仓库,编辑settings.xml如下:

这里写图片描述

    上图中mirrorOf的值为contral,表示该配置为中央仓库的镜像。

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

这里写图片描述

    上图中mirrorOf的值为*号,表示该配置是所有Maven仓库的镜像,任何对于远程仓库的请求都会转至镜像私服。如果该镜像仓库需要认证,则配置一个id为镜像id的server即可。

    为了满足一些复杂的请求,Maven还支持更高级的镜像配置:

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

           <mirrorOf>external:*</mirrorOf>:匹配所有远程仓库,使用localhost的除外,使用file://协议的除外。也就是说匹配所有不在本机上的远程仓库

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

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


    需要注意的是,由于镜像仓库完全屏蔽了被镜像仓库,当镜像仓库不稳定或者停止服务的时候,Maven仍将无法访问被镜像仓库,因而无法下载构件。
仓库搜索服务
    使用Maven进行开发的时候,最常见的问题就是怎么找到它的依赖,我们只知道想要的类库名称,但添加Maven依赖要求提供确切的Maven坐标。这时候就可以使用仓库搜索服务。

        A.  Sonatype Nexus

        地址:http://repository.sonatype.org

        Nexus是流行的开源Maven仓库管理软件,支持关键字搜索,类名搜索,坐标搜索,校验搜索等功能。
        界面如下所示:

        注:因为网络原因该网站一直处于loading阶段

这里写图片描述

        B.  MVNrepository

        地址:http://www.mvnrepository.com/

        MVNrepository界面比较清新,提供了基于关键字的搜索,依赖与被依赖的关系信息,以及一个简单的图表,显示某个构件各版本间大小变化。

        界面如下所示:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值