一、什么是Maven的仓库
我们是否想过一个问题,为什么我们通过Maven配置相应的依赖就可以自动下载相应的依赖包呢?按照我们计算机的思维角度考虑。那么一定是有一个服务或者一个位置提供了这个依赖包的下载。否者Maven不可能会自动的下载,因为没有资源。所以在Maven中提供这个服务或者位置的地方就可以理解为仓库。也就是存储依赖包的地方。在Maven中仓库是有以下几个分类的,下面我们详细介绍一下。
二、Maven仓库的分类
在Maven中为了更方便快捷的下载相关的组件也就是依赖包,Maven对仓库进行了简单的划分。简单来说可以分为本地仓库和远程仓库。
- 本地仓库
这个很容里理解,也就是存储到本地机器地方的仓库,也就是本地仓库。当Maven引入依赖包时,会首先在本地仓库查询是否有符合的依赖包。这里的符合说的是依赖配置是否正确。如果本地仓库存在,则直接可以使用。如果本地仓库没有,则Maven会检查是否有更新的依赖包。然后去远程仓库进行查找。(远程仓库也就是在服务器上的仓库)如果在远程仓库中查找到,则会下载到本地仓库,然后Maven按照上述的方式给项目使用。如果在远程仓库中没有查询到相应的依赖包。则Maven就会抛出异常。下面是我们随便定义了一个组件。
<dependency>
<groupId>cn.ma-zhe</groupId>
<artifactId>mazhe-maven</artifactId>
<version>1.0.0</version>
</dependency>
当我们在项目中执行执行mvn clean package
命令后,Maven就会抛出下面异常:
[ERROR] Failed to execute goal on project midai-mazhe-maven: Could not resolve dependencies for project com.mi-dai.cn:midai-mazhe-maven:jar:1.0-SNAPSHOT: Failure to find mi-dai:mazhe:jar:1.0.0 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]
我们看上面的错误,提示我们没有找到相应的依赖包导致,因为在Maven中本地仓库和远程仓库中都没有找到。
在Maven中默认的本地仓库的路径为当前用户下创建一个/.m2/repository
目录。这个目录就是本地仓库的目录,你本地项目依赖的所有Maven的组建都在这个目录中。例如我本地Maven的仓库目录为:/Users/essfzqbghl/.m2/repository
。当然不同操作系统的目录结构可能是不一样的。但Maven在创建本地仓库的目录规则是一样的。当然我们也可以手动修改本地仓库的默认目录。具体操作如下:
在Maven的下载目录中找到conf目录,这个目录下有一个settings.xml
文件,这个是Maven核心的文件,通过这个文件我们可以设置Maven很多的配置。通过这个文件我们可以找到settings
标签,在这个标签下我们可以找到下面的配置:
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
并且通过上面的内容我们知道这个配置被注释了,当我们解开注释,并且把我们想设置的目录写到<localRepository></localRepository>
标签中即可。
刚刚我们介绍过,当我们在Maven的依赖中配置相关的依赖,Maven就会自动将这个依赖的组件下载到本地仓库中。那么我们怎么能将我们自己开发的组件放到本地仓库中呢?并且这是个很常见的需求。例如我们在实际的工作开发中,如果A项目依赖B项目那么为了保证项目能够正常运行,就需要将B项目的依赖包放到本地的仓库中。那么怎么操作呢。在Maven中很简单就可以实现上面的诉求。也就是我们之前介绍过的,使用mvn clean install
命令。通过这个命令,Maven就会将这个依赖安装到本地仓库中。
可能有人些会遇到,为什么我安装完Maven后,并且成功的配置了Maven的环境变量那么为什么在用户的目录下没有找到本地仓库的路径呢?这个原因很简单,我们想,因为我们Maven的安装是通过配置环境变量的方式实现的,并不是用类似于exe、dmg等安装包的程序配置。所以Maven没办法生成本地仓库的默认路径,因为没办法触发。那么怎么能让Maven自动创建本地仓库呢?答案也很简单。就是当我们第一次输入Maven命令时,Maven就会自动创建本地仓库的路径,并且下载相应的依赖组件。默认情况下,这个目录是隐藏的。
三、远程仓库
下面我们在介绍一下远程仓库,如果我们理解了本地仓库,那么我们很容易理解远程仓库。因为当我们本地仓库找不到想要的依赖组件时,就会通过远程仓库寻找。然后在将远程仓库的中寻找到的依赖组建下载到本地仓库中。这时我们需要思考一下问题,那就是Maven怎么知道去哪个远程仓库寻找依赖组件呢?并且Maven又怎么保证远程仓库一定有我们想要寻找的依赖组件呢?实际上Maven为了解决上述的问题,引入了中央仓库的概念。通过中央仓库就可以完美的解决上面说的所有的问题。下面我们详细介绍一下Maven中的中央仓库。
四、中央仓库
因为当我们第一次输入Maven命令的时候,虽然会创建本地仓库,但是本地仓库的依赖组件是空的,这需要从远程仓库下载依赖组件,那么从哪开始下载呢?于是Maven提供了中央仓库,也就是默认的远程仓库。下面是Maven默认的远程仓库的地址:
https://repo.maven.apache.org/maven2
我们怎么能快速的查询到Maven中中央仓库的地址呢。办法其中有很多种我们介绍一个比较简单的方式,那就是当我们在项目中添加一个本地仓库中没有的依赖时,然后通过Maven的执行日志就可以看到远程仓库的地址了。因为就像这前介绍的那样,当Maven发现本地仓库中没有我们想要的组件时,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">
<parent>
<artifactId>midai-mazhe-maven</artifactId>
<groupId>cn.ma-zhe</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mazhe-maven-mall</artifactId>
<dependencies>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</project>
- 执行Maven编译的命令:
mvn clean compile
。查看日志输出:
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< cn.ma-zhe:mazhe-maven-mall >---------------------
[INFO] Building mazhe-maven-mall 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/net/sf/json-lib/json-lib/2.4/json-lib-2.4.pom
Downloaded from central: https://repo.maven.apache.org/maven2/net/sf/json-lib/json-lib/2.4/json-lib-2.4.pom (13 kB at 27 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/commons-beanutils/commons-beanutils/1.8.0/commons-beanutils-1.8.0.pom
Downloaded from central: https://repo.maven.apache.org/maven2/commons-beanutils/commons-beanutils/1.8.0/commons-beanutils-1.8.0.pom (11 kB at 148 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/11/commons-parent-11.pom
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/11/commons-parent-11.pom (25 kB at 297 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/net/sf/ezmorph/ezmorph/1.0.6/ezmorph-1.0.6.pom
Downloaded from central: https://repo.maven.apache.org/maven2/net/sf/ezmorph/ezmorph/1.0.6/ezmorph-1.0.6.pom (6.8 kB at 97 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/commons-lang/commons-lang/2.3/commons-lang-2.3.pom
Downloaded from central: https://repo.maven.apache.org/maven2/commons-lang/commons-lang/2.3/commons-lang-2.3.pom (11 kB at 159 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/net/sf/json-lib/json-lib/2.4/json-lib-2.4.jar
Downloading from central: https://repo.maven.apache.org/maven2/commons-beanutils/commons-beanutils/1.8.0/commons-beanutils-1.8.0.jar
Downloading from central: https://repo.maven.apache.org/maven2/net/sf/ezmorph/ezmorph/1.0.6/ezmorph-1.0.6.jar
Downloaded from central: https://repo.maven.apache.org/maven2/commons-beanutils/commons-beanutils/1.8.0/commons-beanutils-1.8.0.jar (231 kB at 1.1 MB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/net/sf/ezmorph/ezmorph/1.0.6/ezmorph-1.0.6.jar (86 kB at 242 kB/s)
我们看上面的输出,当本地仓库没有找到我们的依赖包时,Maven就会自动从远程仓库中的中央仓库查询我们的依赖包。并且上面的下载地址就是Maven中央仓库的默认地址。
五、私服
了解了远程仓库和中央仓库之后,我们需要考虑以下几个问题。
- 如果在使用Maven时,如果本地仓库没有,那就需要去远程仓库寻找。那么如果一个公司有很多人都需要请求远程仓库,会不会造成网络的阻塞。
- 全世界所有需要Maven的依赖的都需要访问远程仓库,这对Maven中央仓库也是个非常大的影响。
- 因为个别公司因为安全角度考虑,是禁止公司访问外网资源的,那么这样就会导致无法访问Maven的中央仓库。也就相当于无法使用Maven了。
为了解决上述的问题,Maven支持通过配置的方式,修改默认远程仓库的地址。通过这种方式,我们在使用本地仓库中没有依赖组件时,就会访问我们自己配置的远程仓库地址,这种特殊的远程仓库地址,我们叫做私服。私服可以是本公司的私服也可以是国内的私服,本质就是先访问私服下砸依赖,如果私服没有在去中央仓库下载。通过这样的方式可以带来以下的好处:
-
解决了我们刚刚说的,团队成员全部都访问中央仓库的弊端,只要团队人员一个人下载成功了组件,其它人就可以不用访问中央仓库,而是从私服地址下载,这不但节省了公司网络的带宽,还加快了团队其它成员下载依赖组件的效率。
-
公司在开发的过程中,可以会基于公司自己的需求开发出只能给公司自己使用的组件。这时我们可以将此组件部署到私服中,这样公司团队成员可以像之前依赖其它组件一样,通过配置的方式引入此依赖,而公司以外的人则无法引入此依赖。
-
通过私服的方式增加了Maven的稳定性,因为如果我们访问中央仓库,比较常见的问题会是网络服务中断或者网络下载较慢等情况。这严重影响项目的构建速度。当采用私服的方式时,虽然也可能会出现上述的问题,但是由于是公司内部的搭建的,可以自行解决。
-
这种方式降低了中央仓库的负荷。这样只有本地仓库没有、私服中也没有情况下才需要访问中央仓库,这样间接了保证了中央仓库的稳定性。
国内的私服有很多,比较长常用的私服为阿里云的私服,因为网络问题的原因,我们在使用Maven时常常会觉的很慢,这是因为当本地仓库没有依赖时,需要去中央仓库下载,而中央仓库是外网,所以会非常的慢,所以在实际项目开发中,基本上都会配置私服的地址来解决Maven下载依赖组建慢的问题,本文推荐使用阿里云的私服地址,当然你也可以用其它的,本质是解决慢的问题,实际上是没有任何区别的。下面我们看一下如何配置阿里云的私服。我们还是通过Maven的setting.xml
文件进行配置。具体配置如下:
- setting.xml
<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>
我们找到mirrors
标签,然后添加以下的配置:
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
这样我们就配置完了,然后我们还是通过编译项目的方式,来验证一下,我们配置的是否成功。
- 日志输出
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< cn.ma-zhe:mazhe-maven-mall >---------------------
[INFO] Building mazhe-maven-mall 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] Artifact org.apache.maven.plugins:maven-clean-plugin:pom:3.2.0 is present in the local repository, but cached from a remote repository ID that is unavailable in current build context, verifying that is downloadable from [nexus-aliyun (http://maven.aliyun.com/nexus/content/groups/public, default, releases)]
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-clean-plugin/3.2.0/maven-clean-plugin-3.2.0.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-clean-plugin/3.2.0/maven-clean-plugin-3.2.0.pom (0 B at 0 B/s)
我们看日志输出Maven在找不到依赖包请求远程仓库时,不是从中央仓库寻找了,而是从我们刚刚配置的阿里云的私服地址下载了。这也就证明了,我们的配置生效了。上面配置的方式,实际上是配置了一个Maven的镜像,由于后面的章节中有详细的介绍,所以本篇就不在过多的介绍了。