坐标和依赖是任何一个构件在Maven世界中的逻辑表示方式;而构建的物理表示方式是文件,Maven通过仓库来统一管理这些文件。
一、何为Maven仓库
在Maven世界中,任何一个依赖、插件或者项目构建的输出,都可以称为构件。例如,依赖log4j-1.2.15.jar是一个构件,插件maven-compiler-plugin-2.0.2.jar是一个构件,account-email项目构建完成后的输出account-email-1.0.0-SNAPSHOT.jar也是一个构件。任何一个构件都有一组坐标唯一标识。
得益于坐标机制,任何Maven项目使用任何一个构件的方式都是完全相同的。在此基础上,Maven可以在某个位置统一存储所有Maven项目共享的构件,这个统一的位置就是仓库。实际的Maven项目将不再各自存储其依赖文件,它们只需要声明这些依赖的坐标,在需要的时候(例如,编译项目的时候需要将依赖加入到classpath中),Maven会自动根据坐标找到仓库中的构件,并使用它们。
为了实现重用,项目构建完毕后生成的构件也可以安装或者部署到仓库中,供其他项目使用。
二、仓库的布局
任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这便是Maven的仓库布局方式。例如,log4j:log4j:1.2.15这一依赖,其对应的仓库路径为log4j/log4j/1.2.15/log4j-1.2.15.jar,该路径与坐标的大致对应关系为groupId/artifactId/version/artifactId-version.packaging.
三、仓库的分类
对于Maven来说,仓库只分为两类:本地仓库和远程仓库。当Maven根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在此构件,则直接使用;如果本地仓库不存在此构件,或者需要查看是否更新的构件版本,Maven就会去远程仓库查找,发现需要的构件之后,下载到本地仓库再使用。如果本地仓库和远程都没有需要的构件,Maven就会报错。
在这个最基本分类的基础上,还有必要介绍一些特殊的远程仓库。中央仓库是Maven核心自带的远程仓库,它包含了绝大部分开源的构件。在默认配置下,当本地仓库没有Maven需要的构件的时候,它就会尝试从中央仓库下载。
私服是另一种特殊的远程仓库,为了节省带宽和时间,应该在局域网内架设一个私有的仓库服务器,用其代理所有外部的远程仓库。内部的项目还能部署到私服上供其他项目使用。
除了中央仓库和私服,还有很多其他公开的远程仓库,常见的有Java.net Maven库和JBoss Maven库等。
Maven仓库的分类如下图:
1)本地仓库
一般来说,在Maven项目目录下,没有诸如lib/这样用来存放依赖文件的目录。当Maven在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依赖文件。
默认情况下,不管是在Windows还是linux上,每个用户在自己的用户目录下都有一个路径名为.m2/repository/的仓库目录。例如,笔者的用户名是juven,我在Windows机器上的本地仓库地址为:C:\Users\juven\.m2\repository\,而我在Linux上的本地仓库地址为/home/juven/.m2/repository/。注意,在Linux系统中,以点(.)开头的文件或者目录默认是隐藏的,可以使用ls -a命令显示隐藏文件或目录。
有时候,因为某些原因(例如C盘空间不够),用户会想要自定义本地仓库目录地址。这时,可以编辑文件~/.m2/settings.xml,设置localRepository元素的值为想要的仓库地址。例如:
<settings>
<localRepository>D:\java\repository\</localRepository>
</settings>
这样,该用户的本地仓库地址就被设置成了D:\java\respository\。
需要注意的是,默认情况下,~/.m2/settings.xml文件是不存在的,用户需要从Maven安装目录复制$M2_HOME/conf/settings.xml文件再进行编辑。
2)远程仓库
安装好Maven后,如果不执行任何Maven命令,本地仓库目录是不存在的。当用户输入第一条Maven命令后,Maven才会创建本地仓库,然后根据配置和需要,从远程仓库下载构件至本地仓库。
对于Maven来说,每个用户只有一个本地仓库,但可以配置访问很多远程仓库。
3)中央仓库
由于最原始的本地仓库是空的,Maven必须知道至少一个可用的远程仓库,才能在执行Maven命令的时候下载到需要的构件。中央仓库就是这样一个默认的远程仓库,Maven的安装文件自带了中央仓库的配置。读者可以使用解压工具打开jar文件$M2_HOME/lib/maven-model-builder-3.0.jar,然后访问路径org/apache/maven/model/pom-4.0.0.0.xml,可以看到如下配置:
<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<url>http://repol.maven.org/maven2</url>
</layout></layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
4)私服
私服是一种特殊的远程仓库,它架设在局域网的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。此外,一些无法从外部仓库下载到的构件也能从本地上传到私服上供大家使用,如图所示:
上图所展示的是组织内部使用私服的情况。即使在一台直接连入Internet的个人机器上使用Maven,也应该建立私服。
四、远程仓库的配置