1仓库
由于坐标机制,任何Maven项目使用任何一个构件的方式都是完全相同的。在此基础上,Maven可以在某个位置统一存储所有Maven项目共享这些构件,这个统一的位置就是Maven中央仓库,实际的Maven项目不再依赖各自存储其依赖构件,它们只需要声明这些依赖的坐标,在需要的时候,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仓库的布局方式:
private static final char PATH_SEPARATOR=’/’; private static final char GROUP_SEPARATOR=’.’; private static final char ATRIFACT_SEPARATOR=’-’; public String pathof(Artifact artifact) { ArtifactHandler artifactHandler = artifact.getArtifactHandler(); StringBuilder path = new StringBuilder(128); path.append(formatAsDirectory(artifact.getGroupId())).append(PATH_SEPARATOR); path.append(artifact.getArtifactId()).append(PATH_SEPARATOR); path.append(artifact.getBaseVersion()).append(PATH_SEPARATOR); path.append(artifact.getArtifactId()).append(ATRIFACT_SEPARATOR).append(artifact.getVersion()); if (artifact.hasClassifier()) { path.append(ATRIFACT_SEPARATOR).append(artifact.getClassifier()); } if(artifact.getExtension()!=null&& artifactHandler.getExtension().length() > 0) { path.append(GROUP_SEPARATOR).append(artifactHandler.getExtension()) } return path.toString(); } private String formatAsDirectory(String directory) { return directory.replace(GROUP_SEPATATOR, PATH_SEPARATOR); }
<span style="font-weight: bold; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">2 仓库的分类</span>
对于Maven来说,仓库只分为两种,本地仓库和远程仓库,当Maven根据坐标来寻找构件的时候,如果构件在本地仓库,就直接使用,如果不在本地仓库,就从远程仓库去下载到本地仓库直接使用,如果本地仓库和远程仓库都没这样的构件,则Maven就会报错。
远程仓库可以继续分类,主要有中央仓库、私服、以及其它公共库。
中央仓库是Maven自带的核心仓库,当本地仓库没有想要的构件的时候,就会中央仓库去下载相应的构件。
私服是另一种特殊的远程仓库,为了节省带宽和时间,应该在局域网内架设一个私有的仓库服务器,用其代理外部的远程仓库。内部的项目还能部署到私服上供其它的项目使用,阿里的私服务地址:http://mvnrepo.taobao.ali.com/nexus/index.html。
除了中央仓库和私服以外,还有不少公开的远程仓库,常见的java net maven库(http://download.java.net/maven2/ )和jBoss Maven库(http://repository.jboss.com/maven2/)等。
本地仓库:在windows下默认的地址为:c:\Users\juven\.m2\repository\有时候因为某些原因,用户会想要自定义本地仓库目录地址。这时,可以编辑~/.m2/settting.xml,设置localReposityory元素的值为想要的仓库地址。例如:
<settings> <localRepository>D:\java\repository\</localRepository> </settings>
远程仓库:本地仓库好比就是书房,远程仓库就好比是书店,当我们无法从书房找到需要的书的时候,就会书店购买后放到书房里。当Maven无法从自己的仓库找到需要的构件的时候,就会从远程仓库下载构件到本地仓库。一般地,对于每一个人来说,书房只有一个,但外面的书店有很多,类似的,对于Maven来说,每个用户只有一个本地仓库,但可以配置访问很多远程仓库
中央仓库:中央仓库是一个默认的远程仓库,Maven安装的文件自带了中央的配置。可以用解压工具打开jar文件$/M2_HOME/lib/maven-model-builder-3.0.jar,然后访问路径org/apache/maven/model/pom-4.0.0.xml,可以看到如下的配置:
<repositories> <repository> <id>central</id> <name>Maven Repository Switchboard</name> <url>http://repo1.maven.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
包含这段配置的文件是所有Maven项目都会继承的超级POM,这段配置使用的id central对中央仓库进行唯一标识,其名称为Maven RepositorySwitchboard, 它使用default仓库布局。中央仓库包含了这个世界上绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等,每个月这里接受全世界Java程序员大概1亿次的访问,它对全世界Java开发者的贡献由此可见一斑。由于中央仓库包含了超过2000个开源项目的构件,因些,一般来说,一个简单Maven项目所需要的依赖构件都能从中央仓库下载到。这也解释了为什么Maven能做到“开箱即用”。
私服:私服是一种特殊的远程仓库,这是架设在局域网内的仓库服务,私服代理广域 网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。此外,一些无法从外部仓库下载到的构件也能从本地上传到私服上供大家使用,如下图所示:
3 远程仓库的配置
在很多情况下,默认的中央仓库无法满足项目的需求,可能项目需要的构件存在于另外一个远程仓库中,如JBoss Maven仓库。这时,可以在POM中配置该仓库,代码如下:
<project> <repositories> <repository> <id>jboss</id> <name>JBoss Repository</name> <url>http://repository.jboss.com/maven2</url> <release> <enabled>true</enabled> </release> <snapshots> <enabled>false</enabled> </snapshots> <layout>default</layout> </repository> </repositories> </project>
Maven自带的中央仓库使用的id为central,如果其他的仓库声明也使用该Id,就会覆盖中央仓库的配置,该配置的URL的值指向了仓库的地址。
该例中的layout元素的值default表示仓库的布局是Maven2及Maven3的默认布局,而不是Maven1的布局。
对于release和snapshots来说,除了enabled,它们还包含另外两个元素updatePolicy和checksumPolicy
<snapshots> <enabled>true</enabled> <updatePolicy>daily</updatePolicy> <checksumPolicy>ignore</checksumPolicy> </snapshots>
大部分的远程仓库无须认证就可以访问,但有时候出于安全方面的考虑,我们需要提认证信息才能访问一些远程仓库。假设有一个id为my-proj的仓库配置认证信息,编辑setting.xml文件见代码清单如下:
<settings> <servers> <server> <id>my-proj</id> <username>repo-user1234</username> <password>repo-pwd1234</password> </server> </servers> </settings>
我们工作上本机的配置:
<servers> <server> <id>b2b.repo.server</id> <username>maven</username> <password>secret</password> </server> <server> <id>scm.deploy.account</id> <username>maven</username> <password>secret</password> </server> </servers>
4 仓库解析依赖的机制
1.当依赖的范围是system的时候,Maven直接从本地文件系统解析构件;
2.根据依赖坐标计算仓库路径后,尝试直接从本地仓库寻找构件,如果发出相应构件,则解析成功;
3.在本地仓库不存在相应构件的情况下,如果依赖的版本是显式的发布版本构件,如1.2,2.1-beta-1等,则遍历所有的远程仓库,发现后,下载并解析使用;
4.如果依赖的版本是Release或Last,则基于更新策略读取所有远程仓库的元数据groupId/artifactId/maven-metadata.xml,将其与本地仓库的对应元数据合并后,计算出Release或Last的真实值,然后基于这个值,检查本地和远程仓库;
5.如果依赖的版本是SNAPSHOT,则基于更新策略读取所有远程仓库的元数据group/artifactId/version/maven-metadata.xml,将其与本地仓库的对应元数据合并后,得到最新快照版本的值,然后基于该值,检查本地仓库,或者从远程仓库下载;
6.如果最后解析得到的构件版本是时间戳格式的快照,如果1.4.1-20091104.121450-121,则复制其时间戳格式的文件至非时间戳格式,如SNAPSHOT,并使用该非时间戳格式的构件。
当依赖的版本不明晰的时候,如Release、Last和SNAPSHOT; Maven就要基于更新远程仓库的更新策略来检查更新,下面是基于groupId和artifactId的maven-metadata.xml。
<? xml version=’1.0’ encoding=’UTF-8’?> <metadata> <groupId>org.sonatype.nexus</groupId> <artifactId>nexus</artifactId> <versioning> <latest>1.4.2-SNAPSHOT</latest> <!—最新版本--> <release>1.4.0</release> <!—发布版本--> <versions> <version>1.3.5</version> <version>1.3.6</version> <version>1.4.0- SNAPSHOT </version> <version>1.4.0</version> <version>1.4.0.1-SNAPSHOT</version> <version>1.4.0.2-SNAPSHOT</version> </versions> <lastUpdated>20091214221557</lastUpdated> </versioning> </metadata>
5 镜像
如果仓库X提供仓库Y的所有内容,那么就认为X是Y的一个镜像。http://maven.net.cn/content/groups/public/是中央仓库http://repo1.maven.org/maven2/在中国的镜像,并且该镜像提供比中央仓库更快的服务,可以配置Maven使用该镜像的来代替中央仓库,编辑settings.xml,如下:
<settings> <mirrors> <mirror> <id>maven.net.cn</id> <name>one of the central mirrors in China</name> <url>http://maven.net.cn/content/groups/public/</url> <mirrorof>central</mirrorof> </mirror> </mirrors> </settings>
匹配规则:
<mirrorOf>*</mirrorOf>:匹配所有远程仓库
<mirrorOf>external:*</mirrorOf>匹配所有远程仓库,除了使用localhost除外
<mirrorOf>repo1, repo2</mirrorOf>匹配repo1和repo2
<mirrorOf>*, !repo1</mirrorOf>匹配所有远程仓库,repo1除外
6 仓库搜索服务
目前仓库主要搜索服务有如下三种:1. Sonatype Nexus 地址:http://repository.sonatype.org/
2. Jarvana 地址:http://www.jarvana.com/jarvana/
3. MVNbrowser 地址:http://www.mvnbrowser.com