Maven知识分析

Maven知识分析

注:本博文是接着上一章节继续讲解

Nexus-私有仓库的配置

点击左边导航栏的Repositories选项,会显示一个所有仓库及仓库组的列表,Type字段的值有group,hosted,proxy,virtual(在Maven1中使用,这里不需要关心),如图14所示:

Maven知识分析

图14

在这里:

  • hosted,本地仓库,这个仓库主要是用来存放本地的依赖包,服务于局域网,不访问公网
  • proxy,代理仓库,用来存放nexus从公网中获取的依赖包,这里有中央仓库,Apache和Codehaus开源网站的依赖包
  • group,仓库组,用来合并多个hosted/proxy仓库,通常我们配置maven依赖仓库组

比如点击Type为group,如图15所示:

Maven知识分析

图15

会发现,在Ordered Group Repositories中,有所有hosted和proxy的仓库,而图15中箭头所指的地方有四种类型的仓库,分别是Releases(hosted), Snapshots(hosted), 3rd Party(hosted),Central(proxy),而Central指的是中央仓库,不知道大家是否还有印象,在本系列第二章节,曾经提到中央仓库的位置,存在于apache-maven-3.1.1\lib\maven-model-builder-3.1.1.jar中的org\apache\maven\model\pom-4.0.0.xml文件中,定义了中央仓库的位置,配置文件如下所示

 

 ………………………………………………………………
 <repositories>
<repository>
 <id>central</id>
 <name>Central Repository</name>
 <url>http://repo.maven.apache.org/maven2</url>
 <layout>default</layout>
 <snapshots>
<enabled>false</enabled>
 </snapshots>
</repository>
 </repositories>
 ………………………………………………………………
其中url指向了中央仓库的位置http://repo.maven.apache.org/maven2,

而Releases, Snapshots, 3rd Party,主要功能如下:
Releases: 这里存放我们自己项目中发布的构建, 通常是Release版本
Snapshots: 这个仓库非常的有用, 它的目的是让我们可以发布那些非release版本, 非稳定版本, 比如我们在trunk下开发一个项目,在正式release之前你可能需要临时发布一个版本给你的同伴使用, 因为你的同伴正在依赖你的模块开发, 那么这个时候我们就可以发布Snapshot版本到这个仓库, 你的同伴就可以通过简单的命令来获取和使用这个临时版本
3rd Party: 顾名思义, 第三方库, 你可能会问不是有中央仓库来管理第三方库嘛, 没错, 这里的是指可以让你添加自己的第三方库, 比如有些构件在中央仓库是不存在的. 比如你在中央仓库找不到Oracle 的JDBC驱动, 这个时候我们就需要自己添加到3rd party仓库

在settings.xml中配置远程仓库

既然这个group已经包含了四个仓库,那么只要将这个组进行配置,在Maven中就会引用所有在这个组对应的仓库中的依赖包,配置的URL地址为http://localhost:8081/nexus/content/groups/public/。我们可以配置在项目中的user-parent的pom.xml文件中,但此时会有个问题,这样的配置仅仅是对当前的项目有效(user-parent是父文件,其子文件继承),如果项目有很多,而不需要每个项目都要进行以上设置,也就是只要设置一次,然后本机的项目就会自动从nexus中寻找依赖包,如何做呢?

Maven仓库组

因为Maven在本机中是同一个,所以只要在Maven所对应的settings.xml中进行配置就好,(本博客settings.xml对应的路径为E:\Workspaces\Maven\settings.xml),配置如下:

 

…………………………………………
 <profiles>
  <profile>
  <id>nexusProFile</id>
  <repositories>
   <repository>
    <id>localNexus</id>
<name>Nexus Repository</name>
    <url>http://localhost:8081/nexus/content/groups/public/</url>
    <releases>
     <enabled>true</enabled>
    </releases>
    <snapshots>
 <!-- 此选项默认是关闭的,手动打开 -->
     <enabled>true</enabled>
    </snapshots>
   </repository>
   </repositories>
  </profile>
 </profiles>
 <activeProfiles>
  <!-- 激活上面的配置 -->
  <activeProfile>nexusProFile</activeProfile>
 </activeProfiles>
…………………………………………
Maven中的profile是一组可选的配置,可以用来设置或者覆盖配置默认值。有了profile,你就可以为不同的环境定制构建。
这个时候,做个试验,可以在user-core的pom.xml中加入以下依赖(这个依赖包并不存在于本地或者Nexus仓库中)

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.1.1</version>
</dependency>
添加好后进行保存,会发现Eclipse的控制台中有如图16的信息:
Maven知识分析
图16

这表明,Maven已经从通过Nexus下载依赖包了,而Nexus从中央工厂中进行下载。
接着看图17:

Maven知识分析

图17

这也验证了Nexus已经将mybatis的依赖包下载到了仓库中。
但此时会有个问题,如果将Nexus服务停止,如图18所示

Maven知识分析

图18

这个时候在user-core的pom.xml中添加原来没有的依赖配置文件(可以随便找个不存在的jar依赖文件进行测试,这里用使用Spring)

 

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
这个时候在Eclipse中点击保存,会发现如下的信息
14-3-7 GMT+0800下午8:29:41: [INFO] Using org.eclipse.m2e.jdt.JarLifecycleMapping lifecycle mapping for MavenProject: com.steven.user:user-core:0.0.1-SNAPSHOT @ E:\Workspaces\STSWorkspace\user-core\pom.xml.
14-3-7 GMT+0800下午8:29:42: [INFO] Number of application's worked threads is 4
14-3-7 GMT+0800下午8:29:44: [INFO] Downloaded http://localhost:8081/nexus/content/groups/public/org/springframework/spring-core/3.2.2.RELEASE/spring-core-3.2.2.RELEASE.pom
14-3-7 GMT+0800下午8:29:44: [INFO] Number of application's worked threads is 4
14-3-7 GMT+0800下午8:29:47: [INFO] Downloading http://repo.maven.apache.org/maven2/org/springframework/spring-core/3.2.2.RELEASE/spring-core-3.2.2.RELEASE.pom
14-3-7 GMT+0800下午8:29:47: [INFO] Downloaded http://repo.maven.apache.org/maven2/org/springframework/spring-core/3.2.2.RELEASE/spring-core-3.2.2.RELEASE.pom
………………………………………………………………………………
首先通过Nexus下载,但服务已经关闭,这个时候仍然可以下载,而且通过中央仓库进行下载。但在项目中,不允许本地仓库直接下载中央仓库的依赖包,这个时候就需要进行对中央仓库进行覆盖,使之只能通过Nexus访问中央仓库,这个时候需要对镜像进行配置
在settings.xml中配置镜像

首先配置镜像,使得只有通过Nexus才可以访问中央仓库

 

…………………………………………………………
<mirror>
 <id>nexusMirror</id>
 <mirrorOf>*</mirrorOf>
 <name>Human Readable Name for this Mirror.</name>
 <url>http://localhost:8081/nexus/content/groups/public/</url>
</mirror>
…………………………………………………………
这里的*号代表所有的仓库都是通过这个url地址访问,这个时候可以附加一段配置,原来的中央仓库中snapshots版本的依赖包默认是不可以下载的,但可以通过以下配置进行修改

 

 ……………………………………
 </profiles>
 ……………………………………
 <profile>
  <id>centralProFile</id>
  <repositories>
   <repository>
  <id>central</id>
  <name>Central Repository</name>
<!--由于配置过镜像,这个url不起作用-->
  <url>http://repo.maven.apache.org/maven2</url>
  <layout>default</layout>
  <snapshots>
 <!--覆盖中央仓库中的false配置,可以从中央仓库中下载snapshot版本-->
 <enabled>true</enabled>
  </snapshots>
 </repository>
   </repositories>
  </profile>

 </profiles>
 <activeProfiles>
  <!-- 激活上面的配置 -->
  <activeProfile>centralProFile</activeProfile>
 </activeProfiles>
 ……………………………………
这样进行保存后,既可生效。
注意:配置文件settings.xml中会默认有相应的mirror和profile的例子,但都是注释掉的,我们在进行以上的改动时候,可以进行对其复制粘贴后进行修改,这样不容易出错。
验证:(此时没有打开nexus服务)

随便找个不存在的jar依赖文件进行测试,

 

<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
</dependency>
跟刚才的步骤一样,但此时保存后,Eclipse控制台中的信息如下所示:
14-3-7 GMT+0800下午9:13:58: [INFO] Downloaded http://localhost:8081/nexus/content/groups/public/org/mortbay/jetty/jetty/6.1.25/jetty-6.1.25.pom
14-3-7 GMT+0800下午9:13:58: [INFO] Using org.eclipse.m2e.jdt.JarLifecycleMapping lifecycle mapping for MavenProject: com.steven.user:user-service:0.0.1-SNAPSHOT @ E:\Workspaces\STSWorkspace\user-service\pom.xml.
14-3-7 GMT+0800下午9:13:58: [INFO] Number of application's worked threads is 4
14-3-7 GMT+0800下午9:14:02: [INFO] Using 'UTF-8' encoding to copy filtered resources.
14-3-7 GMT+0800下午9:14:02: [INFO] skip non existing resourceDirectory E:\Workspaces\STSWorkspace\user-service\src\main\resources
14-3-7 GMT+0800下午9:14:02: [INFO] Using 'UTF-8' encoding to copy filtered resources.
14-3-7 GMT+0800下午9:14:02: [INFO] skip non existing resourceDirectory E:\Workspaces\STSWorkspace\user-service\src\test\resources
这里只能通过Nexus下载依赖包,但是由于服务停止,所以下载失败,而如果此时将服务打开

Maven知识分析
图19

然后在Eclipse中刷新依赖包所在的pom.xml文件,
如果没有任何问题,则在控制台中显示如下信息:

 

14-3-8 GMT+0800上午12:00:31: [INFO] Downloading http://localhost:8081/nexus/content/groups/public/org/mortbay/jetty/jetty-util/6.1.26/jetty-util-6.1.26.jar
14-3-8 GMT+0800上午12:00:31: [INFO] Downloaded http://localhost:8081/nexus/content/groups/public/org/mortbay/jetty/jetty-util/6.1.26/jetty-util-6.1.26.jar
但此时可能出现以下问题
[ERROR] Could not calculate build plan: Plugin org.apache.maven.plugins:maven-resources-plugin:2.5 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-resources-plugin:jar:2.5
原因:这是因为在进行配置后,所有本地仓库的依赖包都将通过nexus私有仓库访问中央仓库进行下载,而此时在加载一些Maven插件的时候,由于一开始本地仓库中已经存在,而私有仓库中没有这些依赖包的索引(就是指在nexus中存在对依赖包的GAV标识),这个时候就会容易报错。
解决思路:
思路1:
一开始可以进行对索引更新,具体参照图20所示

Maven知识分析

图20

这样设置以后, Nexus会自动从远程中央仓库下载索引文件,索引文件很大,需要很久等待时间。

思路2:

错误信息也有如下所示的提示:

 

Could not calculate build plan: Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.7.1 from http://repo1.maven.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. Original error: Could not transfer artifact org.apache.maven.plugins:maven-surefire-plugin:pom:2.7.1 from/to central (http://repo1.maven.org/maven2): Access denied to http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-surefire-plugin/2.7.1/maven-surefire-plugin-2.7.1.pom.
解决方案:
1.找到maven库目录,进入:\repository\org\apache\maven\plugins\maven-surefire-plugin\2.7.1
2.若2.7.1目录下只有,"maven-surefire-plugin-2.7.1.pom.lastUpdated" 则需要到http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-surefire-plugin/2.7.1/,把里面的文件下载下来放到2.7.1文件夹中
3.删除2.7.1下的maven-surefire-plugin-2.7.1.pom.lastUpdated文件。
4.项目右键-->maven-->Update Project即可。
思路3:

首先关掉Eclipse,停止Nexus运行,然后将本地E:\Workspaces\Maven\repository中所有的依赖包删除,然后启动Nexus,打开Eclipse,这时候将通过Nexus进行下载依赖包到本地仓库中,一般情况可以解决问题,如果还有思路2中的错误信息,则执行思路2。

通过Maven部署项目到Nexus中

当项目已经编写完成,需要部署到Nexus中,这样团队人员可以通过Nexus下载到自己的本地仓库中,比如说,我是编写user-core的模块的,部署到Nexus中,需要以下两个步骤,

1、需要配置user-core的pom.xml文件,定义发布的版本以及发布到Nexus本地库的哪个仓库中,具体如下所示:

 

………………………………………………………………
<distributionManagement>
<repository>
<id>user-core-release</id>
<name>user core release</name>
<url>http://localhost:8081/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>user-core-snapshot</id>
<name>user core snapshot</name>
<url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
………………………………………………………………

2、配置本地settings.xml文件,让部署过程中有足够的权限,而Nexus中本来存在的有三个用户,如图21所示:

Maven知识分析

图21

而部署使用deployment用户,具体的配置如下

 

………………………………………………………………
<server>
   <id>user-core-release</id>
   <username>deployment</username>
   <password>deployment123</password>
</server>
<server>
   <id>user-core-snapshot</id>
   <username>deployment</username>
   <password>deployment123</password>
</server>
………………………………………………………………

完成以上两个步骤,此时进行部署(deploy)操作,如图22所示:

Maven知识分析

图22

这个时候部署成功,然后我们可以在Nexus中看到部署后的结果,如图23所示

Maven知识分析

图23

在Snapshots的索引中可以查看到刚刚部署的user-core模块。

通过Nexus搜索构件

首先我们来明确一下构件的含义,

构件:构件是系统中实际存在的可更换部分,它实现特定的功能,符合一套接口标准并实现一组接口,而在我们这里就是我们要使用的即将需找的依赖。

但在我们实际使用构件的过程中通常遇到一个问题,有时候我紧紧知道我所需要的构建的大致名字,并不知道全称或group id, 这是件非常头疼的事情. Nexus基于Nexus indexer(索引)的搜索功能帮我们解决了这个问题。

还记得刚才我们在解决Could not calculate build plan...问题的时候,给出的思路1,其思想就是,通过更改Download Remote Indexes的状态为True,使得Nexus从中央仓库中将所有构件的信息同步到本地,这样在以后的开发中,就可以直接下载私有仓库中的依赖,就不需要Nexus还要去中央仓库中下载了。下面就来领略Nexus搜索构件的方便之处。

如图所示:

Maven知识分析

图24

这里有以下几种搜索方式:

keyword(关键字查询), classname(类名查询), GAV(groupId,artifactId,version组合查询), checksum(校验和查询),这里我认为前三种使用的最多。

比如,刚刚通过部署后的user-core模块,这个模块正好被其他项目人员使用到,他知道模块的名称叫user-core,这个时候,可以通过GAV的方式进行查询,如图所示:

Maven知识分析

图25

查出来之后,只要将依赖文件复制到项目的pom.xml配置中,就可以从私有仓库中下载到其本地仓库进行使用了。

创建本地仓库并设置权限

创建仓库

在大公司的项目开发中,不可能所有的Snapshots和Releases版本都发布到Nexus中默认对应的Snapshots和Releases仓库中,我们可以给每个项目创建自己的本地仓库,并赋予相应的角色权限进行操作。比如创建一个UserRelease仓库用来存储User项目的Release版本,这个时候,操作如图所示:

Maven知识分析

图26

接着将信息填入New Hosted Repository中,如图27所示

Maven知识分析

图27

这个时候就创建了UserRelease的本地仓库,如图所示

Maven知识分析

图28

创建权限

虽然我们已经创建了UserRelease仓库,但仓库的权限仅为预览,如果让其可以有增删改查的权限,只要点击图中Add,如图所示:

Maven知识分析

图29

接着进行信息填入,如图30所示

Maven知识分析

图30

这个时候UserRelease仓库就拥有了所有的权限,如图31所示

Maven知识分析

图31

创建角色

虽然有了权限,但在使用的过程中,进一步创建一个角色,对角色添加相应的权限,然后在让角色中添加相应的用户,这样在发布的时候就可以达到权限的最细致化,管理起来更加方面。

如图32,创建角色

Maven知识分析

图32

然后进行填写信息,如图33

Maven知识分析

图33

在这里有Add按钮,点击按钮的时候进行如下操作

Maven知识分析

图34

此时,创建角色后如图35所示:

Maven知识分析

图35

创建用户

角色创建好后就可以创建用户,通过专有的用户来进行专有项目的部署和其他操作,如图创建用户

Maven知识分析

图36

然后填入信息,如图所示

Maven知识分析

图37

在图37中点击Add按钮出现图38所示的选项,如下操作

Maven知识分析

图38

就是选择该用户所属的角色,而角色拥有所有的权限,完成后如图39所示

Maven知识分析

图39

注:在以上操作中,我们首先创建一个本地仓库(这里是Release版本的,项目中可以在创建一个Snapshot版本,操作过程同上),然后给这个仓库赋予权限,然后将这些权限通过一个角色进行拥有,当然在这里可以创建不同的角色赋予不同的权限,这时候,创建一个用户,使得该用户担当一个角色,这样的话,这个用户就可以拥有这个角色中的权限,下面就可以按需对所在的项目使用相应的用户进行操作了。

这样根据以上情况可以建立UserSnapshot的仓库,以及将所有的权限付给不同的角色,或者可以让UserReleaseRole同样拥有UserSnapshot的所有权限,并且同样的用户拥有Release和Snapshot仓库的所有权限,这样的话如果进行部署,就可以如下进行配置,在对应部署模块的pom.xml中可以这样配置

 

………………………………………………………………
<distributionManagement>
<repository>
<id>user-core-release</id>
<name>user core release</name>
<url>http://localhost:8081/nexus/content/repositories/UserRelease/</url>
</repository>
<snapshotRepository>
<id>user-core-snapshot</id>
<name>user core snapshot</name>
<url>http://localhost:8081/nexus/content/repositories/UserSnapshots/</url>
</snapshotRepository>
</distributionManagement>
………………………………………………………………

而在settings.xml中就可以这样进行配置

 

………………………………………………………………
<server>
   <id>user-core-release</id>
   <username>UserRelease</username>
   <password>user123</password>
</server>
<server>
   <id>user-core-snapshot</id>
   <username>UserRelease</username>
   <password>user123</password>
</server>
………………………………………………………………

这样就可以把相应的Release和Snapshot版本部署到相应的Nexus仓库中了。

总结

本章节通过对仓库管理器Nexus的讲解,包括如何下载安装Nexus,配置Nexus代理中央仓库,管理Nexus的代理仓库,本地仓库,以及仓库组。并帮助你了解如何通过Nexus搜索构件。最后,如何在Maven中配置Nexus仓库,以及如何部署构件到Nexus仓库中。同时,根据大公司的要求,创建了专有的仓库,并且学习了如何进行用户管理,角色权限管理等等。

如有什么疑问或者建议意见都可以提出,本人在此不胜感激,同时,同样恭祝大家学习愉快!