maven详解4:仓库详解
maven是如何找到我们依赖的jar的
什么是仓库
仓库的分类
各种类型仓库详解
maven中远程仓库配置详解
关于构建问题版本说明
构件文件的布局
学习本章内容之前,先看几个问题:
1、maven如何将依赖的jar引入项目中
2、maven是从什么地方获取依赖的jar包的
3、我们如何掌握获取jar包的获取方式
4、maven是如何组织管理构件的
一、maven如何将需要的jar包引入项目
我们搭建一个maven项目,然后在pom文件中使用之前讲的方法导入一个需要的jar坐标,比较启动前后项目占存储空间的大小,发现项目并没有增加多大,然后在~/.m2/repository中查找下载的对应的jar包,会发现这个jar包远比项目增加的大小大。这说明了什么?
说明我们的项目目录中并没有包含这个jar包,只是对这个jar包做了引用
如果系统中有多个项目,都采用同一个maven来引用依赖的jar包,那么这些jar包只会在磁盘存储一份,就可以被多个项目都使用。使用时只需要在pom.xml中通过maven坐标的方式来对这些jar包进行引用,而需要进行升级,删除的话,只需要在pom.xml中更改版本就行了,非常方便。
结论:maven采取引用的方式将依赖的jar引用进来,不对真实的jar进行拷贝,但是打包的时候,会将需要的jar包拷贝到安装包中
二、maven如何寻找需要的jar
当我们需要jar包时,只需要将这些jar的坐标添加到pom.xml中,maven是如何寻找对应的jar的呢?
maven官方给我们提供了一个站点,该站点存放了很多第三方开发的jar\war\zop\pom等,当额哦们需要时,只需要将坐标写入pom.xml,maven会从站点下一个jar包到本地目录,然后进行自动引用
这个站点我们叫做maven的中央仓库,本地目录叫做本地仓库。
默认情况下,当项目中引入依赖的jar包时,maven会先到本地仓库中进行检索,如果本地仓库中没有,maven会再到中央仓库中寻找,如果有,就下载到本地仓库中,再进行引用,如果没有两个地方都没有,就会报错。
三、什么是maven仓库
在maven中,任何一个依赖,插件或项目构件的输出,都可称之为构件。
在maven中,仓库就是一个位置,这个位置用来存放各种第三方构件,所有的maven项目可以共享这个仓库中的构件
maven仓库可以帮助我们管理构件,主要是jar包,它就是放置各种构件的地方。
仓库的分类
主要分为2大类:
本地仓库、远程仓库
远程仓库又可以分为:中央仓库、私服、其他公共远程仓库
本地仓库:
默认情况下,maven的本地仓库默认地址是“~/.m2/respository”目录,这个默认我们也可以在~\.m2\settings.xml文件中进行修改:
<localrepository>本地仓库的地址<localrepository/>
当我们需要构件的时候,maven会从远程仓库将构件下载到本地仓库目录中。
maven的本地仓库,在maven安装后并不存在,只有当我们执行第一条maven命令的时候本地仓库才会被创建,此时会从远程仓库下载需要的构件到本地仓库给maven项目使用。
需要注意的是,默认情况下,~/.m2/settings.xml这个文件是并不存在的,我们需要从maven的安装目录中拷贝conf/settings.xml,将此文件拷贝到~\.m2中,然后对~\.m2\settings.xml进行编辑。conf/settings.xml这个文件也是可以使用,但是这个是系统级的,修改后可能会影响其他所有使用者,也不利于以后maven的升级,如果我们使用~\.m2\settings.xml,而maven安装目录不动,升级的时候只需要替换一下安装包就好了,这个是用户级别的。
远程仓库:
最开始我们使用maven的时候,本地仓库中的构件是空的,此时maven必须提供一种到外部过去这些构件的功能,而外部就是所谓的远程仓库,远程仓库可以有多个,本地仓库找不到构件时,就到远程仓库中下载。
中央仓库:
由于maven刚安装好的时候,什么都没有配置,本地仓库是空的,去执行maven命令的时候,我们会看到maven默认执行了一些下载操作,这个下载地址就是中央仓库的地址,这个地址是maven社区为我们提供的,是maven内置的一个默认的远程仓库地址,不用用户进行配置。
这个地址在maven安装包的什么地方呢?
我们使用的是3..6.1,在下面这个位置:
apache-maven-3.6.1\lib\maven-model-builder-3.6.1.jar\org\apache\maven\model\pom-4.0.0.xml
在pom-4.0.0.xml中,如下:
<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>
中央仓库的地址就是https://repo.maven.apache.org/maven2
中央仓库的特点:
1、中央仓库是maven社区提供的
2、maven内部已经集成好了
3、使用时maven必须处于联网状态
私 服:
私服也是远程仓库中的一种,我们为什么需要私服呢?
如果我们一个团队中有几百个人在开发一些项目,都是采用maven的方式来组织项目,那么我们每个人都需要从远程仓库中把需要依赖的构件下载到本地仓库,这对公司的网络要求也比较高,为了节省这个宽带和加快下载速度,我们在公司内部局域网内部可以架设一台服务器,这台服务器起到一个代理的作用,公司里面的所有开发者去访问这个服务器,这台服务器将需要的构建返回给我们,如果这台服务器中也没有我们需要的构建,那么这个代理服务器会去远程仓库中查找,然后将其先下载到代理服务器中,然后再返回给开发者本地的仓库。
还有公司内部有很多项目之间会相互依赖,你可能是架构组的,你需要开发一些jar包给其他组使用,此时,我们可以将自己jar发布到私服中给其他同事使用,如果没有私服,可能需要我们手动发给别人或者上传到共享机器中,不过管理起来不是很方便。
总体上来说私服有以下好处:
-
加速maven构件的下载速度
-
节省宽带
-
方便部署自己的构件以供他人使用
-
提高maven的稳定性,中央仓库需要本机能够访问外网,而如果采用私服的方式,只需要本机可以访问内网私服就可以了
关于私服,后面会专门有一篇文章会做详细介绍。
其他远程仓库:
中央仓库是在国外的,访问速度不是特别快,所以有很多比较大的公司做了一些好事,自己搭建了一些maven仓库服务器,公开出来给其他开发者使用,比如像阿里、网易等等,他们对外提供了一些maven仓库给全球开发者使用,在国内的访问速度相对于maven中央仓库来说还是快了不少。
还有一些公司比较牛,只在自己公开的仓库中发布构件,这种情况如果要使用他们的构件时,需要去访问他们提供的远程仓库地址。
构建文件的布局:
我们来看一下构件在仓库的文件结构中是如何组成的?
这块我们以本地仓库来做说明,远程仓库中组织构件的方式和本地仓库是一样的,以fastjson在本地仓库中的信息为例来做说明,如下:
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency>
上面是fastjson 1.2.62这个jar,我们看一下这个jar在本地仓库中的位置:
~\.m2\repositroy\com\alibab\fastjson\1.2.61\fastjson-1.2.62.jar
~\.m2.repository\是仓库的目录,所有本地构件都位于该目录中,我们主要看一下后面是怎么构成的,构件所在目录的构成如下:
groupId+"."+artifactId+"."+版本号
通过上面获取一个字符串,字符串由三个元素之间有 . 连接,然后将这个 . 替换为文件目录分隔符,然后创建多级目录。
而构件文件的组成如下:
[argifactId][-version][-classifier].[type]
上面的fastjson-1.2.62.jar信息如下:
artifactId为fastjson , version为1.2.62 , classifier为空 ,type默认为jar
关于构件版本问题:
平时我们开发项目的时候,打包测试,或者将自己开发的构建提供给他人使用时,中间我们反反复复的打包测试,会给使用方提供很多不稳定的版本,最终经过同事和测试反复验证修改,我们会发布一个稳定的版本。
在发布稳定版本之前,会有很多个不稳定的测试版本,我们版本我们称为快照版本,用SNAPSHOT表示,我们搭建项目时pom.xml文件默认是快照版本的,如下:
<version>1.0-SNAPSHOT<version/>
version以-SNAPSHOT
结尾的,表示这是一个不稳定的版本,这个版本我们最好只在公司内部测试的时候使用,最终发布的时候,我们需要将-SNAPSHOT
去掉,然后发布一个稳定的版本,表示这个版本是稳定的,可以直接使用,这种稳定的版本我们叫做release
版本。
当我们想控制构件获取的远程地址时,我们该怎么做呢?此时需要使用远程仓库的配置功能。
4、maven中远程仓库的配置
此处我们讲解2种方式:
方式1:
在pom.xml中配置远程仓库,语法如下:
<repository> <repository> <id>aliyun-releases<id/> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> <repository/> <repository/>
在repositories元素下,可以使用repository子元素声明一个或多个远程仓库。
repository元素说明:
id:远程仓库的一个标识,中央仓库的id是central,所以添加远程仓库的时候,id不要和中央仓库重复,会把中央仓库覆盖掉
url:远程仓库地址
releases:主要用来配置是否需要从这个远程仓库中下载稳定版本构件
snapshots:主要用来配置是否需要从这个远程仓库中下载快照版本构件
releases和snapshots中有个enabled
属性,是个boolean值,默认为true,表示是否需要从这个远程仓库中下载稳定版本或者快照版本的构建,一般使用第三方的仓库,都是下载稳定版本的构建。
快照版本的构建以-SNAPSHOT
结尾,稳定版没有这个标识。
在pom中配置远程仓库的方式只对当前项目有效,如果我们需要对所有项目都有效,用下面这种方式:
方式2:
镜像方式:在settings.xml中配置
如果仓库x可以提供仓库y所有的内容,那么我们就可以认为x是y的一个镜像,通俗点说,可以从y获取的构建都可以从它的镜像中获取
可以采用镜像的方式配置远程仓库,镜像在settings.xml中进行配置,对所有使用该配置的maven项目起效,配置方法如下:
<mirror>
<id>mirrorId<id/>
<mirrorOf>repositoryId<mirrorOf/>
<name>镜像名称,对该镜像的描述<name/>
<url>http://my.repository.com/repo/path</url>
</mirror>
mirrors元素下面可以有多个mirror元素,每个mirror元素表示一个远程镜像,元素说明:
id:镜像的id,是一个标识
mirrorof:指定那些远程仓库可以使用该镜像,这个对pom.xml文件中的repository元素的id,就是表示该镜像是给那些pom.xml中的远程仓库使用的,这里需要列出远程仓 库的id,多个之间用 逗号隔开,*表示给所有远程仓库做镜像
url:镜像对应远程仓库的地址
name:镜像的名称,相当于一个描述
这里主要对mirrorOf再做一下说明,上面我们在项目中定义远程仓库的时候,pom.xml文件的repository元素中有个id,这个id就是远程仓库的id,而mirrorOf就是用来配置哪些远程仓库会走这个镜像去下载构件。
mirrorof的配置有以下几种:
<mirrorof>*<mirrorof/> 上面匹配所有远程仓库的id,这些远程仓库都会走这个镜像下载构件
<mirrorof>远程仓库1的id,远程仓库2的id<mirrorof/> 指定仓库走这个镜像下载构件
<mirrorof>*,! repo1<mirrorof/> 排除仓库1,所有远程仓库都走这个镜像
**需要注意的是,镜像仓库完全屏蔽了被镜像的仓库,所以当镜像仓库无法使用的时候,maven是无法自动切换到被镜像的仓库的,此时下载构件会失败。
示例:
一个pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacode2018</groupId> <artifactId>maven-chat03</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.2.1.RELEASE</version> </dependency> </dependencies> </project>
settings.xml文件,加入镜像配置,如下:
<mirrors> <mirror> <id>mirror-aliyun-releases</id> <mirrorOf>*</mirrorOf> <name>阿里云maven镜像</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> </mirrors>
关于镜像一个比较常用的用法是结合私服一起使用,由于私服可以代理所有远程仓库(包含中央仓库),因此对于maven用来来说,只需通过访问一个私服就可以间接访问所有外部远程仓库了,这块后面我们会在私服中做具体说明。