一起学Maven

转载自:http://blog.csdn.net/songdeitao/article/details/18452459

 

一. 初识Maven

开场白

    在现在的项目开发过程中,越来越重视项目的管理,而且主流的项目管理框架或者说是工具已经慢慢被Maven取代,在求职者面试过程中,项目开发过程 中,Maven的使用已经成为主流,如何很快着手Maven的项目管理,已经成为包括我在内的很多程序员考虑的问题,在本系列博文中,我将以一个初识 Maven的角度和大家共同学习Maven的项目构建工具的使用,在这个过程中,有可能有很多问题,也或许有很多我没有考虑到的地方,还请高手给予指正, 当然,如果是新入手的学者,也可以在实验过程中给出想法和建议,在此感激不尽。下面进入Maven的学习之路。

什么是Maven?

    Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。类似于大家熟知的Ant工具所起到的效果,当然他们之间存在很多异同点。

为什么要学Maven?

    大家会发现,在平时项目中,我们每天有相当一部分时间花在了编译、运行单元测试、生成文档、打包和部署等烦琐且不起眼的工作上,如果你使用Ant,会发现 很多东西都要程序员去定义,去编写build文件,然而有了Maven这个构建工具,能够帮我们自动化构建过程,从清理、编译、测试到生成报告,再到打包 和部署。我们不需要也不应该一遍又一遍地输入命令,一次又一次地点击鼠标,或者小心翼翼的写着配置文件,我们要做的是使用Maven配置好项目,然后输入 简单的命令(如mvn clean install),Maven会帮我们处理那些烦琐的任务。这一切都体现了一句经典“约定优于配置”,当然Maven不仅是构建工具,还是一个依赖管理工具和项目信息管理工具,况且Maven也是跨平台的。这些都会通过实例说明。

获取和安装

    下载地址:http://maven.apache.org/download.cgi,进去之后,会发现有很多版本,我们将使用较新的版本apache-maven-3.1.1-bin.zip,  (windows平台)如图1所示:


      图1

    如果想查看源码可以下载src版本,当然也可以选择其他操作系统,比如linux平台下的文件,本系列只介绍windows平台下,其他平台还请参照其他博文讲解。

找到下载后的文件,并将文件解压到一个自己定义的目录,如图2所示:


                  图2

    此时发现有四个目录,下面讲解四个目录中文件的作用

    bin目录:

    该目录包含了mvn运行的脚本,这些脚本用来配置java命令,准备好classpath和相关的java系统属性,然后执行java命令

    boot目录:

    该目录只包含一个文件,该文件为plexus-classworlds-xxx.jar。plexus-classworlds是一个类加载器框架,相对于默认的java类加载器,它提供了更丰富的语法以方便配置,maven使用该框架加载自己的类库。

    conf目录:

    该目录包含了一个非常重要的文件settings.xml。直接修改该文件,就能在机器上全局地定制maven的行为。一般情况下,我们更偏向于复制该文件至~/.m2/目录下(~表示用户目录),然后修改该文件,在用户范围定制maven的行为。

    lib目录:

    该目录包含了所有maven运行时需要的java类库。

环境变量的配置

    打开系统属性(桌面上右键单击“我的电脑”→“属性”),点击高级系统设置,再点击环境变量,在系统变量中新建一个变量,变量名为M2_HOME,变 量值为Maven的安装目录E:\StudySoftware\javaEE\apache-maven-3.1.1(根据自己安装的情况)。点击确定, 接着在系统变量中找到一个名为Path的变量,在变量值的末尾加上%M2_HOME%\bin;,注意多个值之间需要有分号隔开,然后点击确定。至此,环 境变量设置完成,详细情况如图3所示:


                           图3

    下面将查看配置是否正确,打开命令控制台,输入mvn -v如果发现图4所示的信息,配置就是成功的:


                        图4

    至此,Maven的环境变量配置成功。

本地仓库

由于运行过mvn命令,那么会在用户目录下发现一个.m2文件,如图5所示:


                       图5
    其中repository目录,这个目录是存放从网上下载下来的jar,而这些jar就是maven的好处之一,可以自动下载项目中用到的jar包,而这些jar包的存放位置就是一个仓库,存放在本地的就是本地仓库,而存放在网络上的就是maven的中央仓库。

    由于下载jar文件的增多,会给C盘造成负担,或者在重装系统后,c盘的东西将不复存在,因此可以把repository目录转移到其他盘中储存。

具体做法是:

1. 复制repository目录到其它盘符,本文中是在E:\Workspaces\Maven下

2. 复制刚刚解压好的Maven目录中,conf中的settings.xml文件到E:\Workspaces\Maven目录下,

3. 打开找到如下内容

<localRepository>....</localRepository>改成:

<localRepository>E:/Workspaces/Maven/repository</localRepository>

同样将conf下的settings.xml也改成如上配置,如图6所示:



                       图6

保存.完成.

这样就将本地仓库从C:\Users\Steven\.m2\repository移到了E:\Workspaces\Maven\repository中。

Maven小实例

本文在目录E:\Workspaces\STSWorkspace\Maven_01(可以随便找个目录)下,新建pom.xml文件,然后在其中加入如下配置:

 

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"   
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
  4.     <modelVersion>4.0.0</modelVersion>  
  5.     <groupId>com.steven.maven</groupId>  
  6.     <artifactId>maven_01</artifactId>  
  7.     <version>0.0.1-SNAPSHOT</version>  
  8. </project>  

其中

    groupId:

    项目或者组织的唯一标志,并且配置时生成路径也是由此生成,如com.steven.maven生成的相对路径为:/com/steven/maven
    artifactId:

    项目的通用名称
    version:

    项目的版本
    接下来在此文件夹中建立src文件夹,然后在src中建立main和test文件夹,然后在main中建立java文件夹,然后在java文件夹中建立com/steven/maven/HelloWorld.java文件,如图7所示:


                         图7

HelloWorld.java的内容如下:

 

  1. package com.steven.maven;  
  2.   
  3. public class HelloWorld{  
  4.     public void sayHello(){  
  5.         System.out.println("Hello Maven!");  
  6.     }  
  7. }  

然后在命令控制台中执行mvn compile,如图8所示:


                          图8

    会发现出现Downloading下载的提示,这是因为,Maven在执行命令的时候,要加载其他使用到的插件和其他jar包,称为依赖,这个时候就要从 网络上进行下载,所以如何使用Maven,请保持网络是正常的,否则会出现问题。当编译完成的时候出现成功的提示信息,如图9所示:


                      图9

此时发现项目目录中多了一个target的目录,如图10所示:


                     图10

    发现刚刚编译产生的class文件放在了target目录下,所以只要我们按照这个目录格式编写,maven工具就帮助我们执行出结果,然后放在相应的结构目录下。

    下面我们将继续编写测试代码,在test目录下新建java文件夹,然后同样新建com/steven/maven/HelloWorldTest.java文件,其中HelloWorldTest文件的内容如下:

 

  1. package com.steven.maven;  
  2. import org.junit.*;  
  3. public class HelloWorldTest{  
  4.     @Test  
  5.     public void sayHelloTest(){  
  6.         HelloWorld hw = new HelloWorld();  
  7.         hw.sayHello();  
  8.     }  
  9. }  

此时的目录结构如图11所示:


                       图11

然后控制台执行mvn test命令,但此时出现错误信息,如图12所示:


                      图12

这是因为测试过程中用到了junit的包,但没有找到,原来的解决办法是:

  • 通过将junit的包加入到环境变量下即可解决

但maven的解决思路是

  • 在pom.xml中加入<dependencies>节点,完成的配置文件如下所示:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"   
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
  4.     <modelVersion>4.0.0</modelVersion>  
  5.     <groupId>com.steven.maven</groupId>  
  6.     <artifactId>maven_01</artifactId>  
  7.     <version>0.0.1-SNAPSHOT</version>  
  8.   
  9.     <dependencies>  
  10.         <dependency>  
  11.             <groupId>junit</groupId>  
  12.             <artifactId>junit</artifactId>  
  13.             <version>4.10</version>  
  14.         </dependency>  
  15.     </dependencies>  
  16. </project>  

    <dependencies>节点代表项目依赖的jar包,然后加入junit的jar包配置文件即可,此时再次执行mvn test,会发现如图13所示的结果:


                       图13

    这时候maven从网络上下载4.10版本的junit jar包,最后的执行结果如图14所示:


                      图14

    此时发现测试成功,正确执行Hello Maven!的结果。

    此时再来看target中的文件会发现如图15所示的结果:


                      图15

    如果此时执行mvn clean命令,如图16所示:


                      图16

    会发现在下载相应插件的同时,执行了清除target目录的操作,然后再来看Maven_01目录中的文件,如图17所示:


                          图17

发现target目录已经不存在了,即被maven clean命令清空了。如果接着执行maven test,会发现target目录又出现了。

    这个时候再来观察一下一开始配置的本地仓库中的文件,会发现图18的结果:


                           图18

我们发现,Maven在执行命令的过程中用到的jar都已经在本地仓库中储藏了,至此,Maven小实例结束。

总结

    在本节中,通过Maven的介绍,下载,安装,配置,已经小实例的实现,估计大家也多多少少有些头绪了,通过实例,可以看出Maven可以作为项目的构建 工具,而配置文件很好写,而且写的很少,用到的jar包,不需要手动去添加到环境变量中,只要通过配置,Maven就会通过网络寻找到并且下载到本地仓库 中。

    在本节中用到的Maven命令:

    mvn compile编译java文件

    mvn test执行junit操作

    mvn clean清空target目录操作

    在此恭祝大家学习愉快!

 

二. eclipse中的项目构建

 

前情回顾

 

    在上一节中介绍了Maven的基本安装配置,以及通过一个小实例认识一下maven的基本架构,一切都是通过手动去搭建的,本节将通过工具讲解Maven在Eclipse中如何构建项目的,然后如何去执行相应的操作。

 

知识补充

 

    一:

 

    在上节提到中央仓库,在此给出如何找到中央仓库的链接,在Maven解压后的目录中,在lib下,有个maven-model-builder- 3.1.1.jar,(E:\StudySoftware\javaEE\apache-maven-3.1.1\lib\maven-model- builder-3.1.1.jar),用解压缩工具打开后,找到pom-4.0.0.xml文件,打开后,即可找到中央仓库定义的url链接,如图1所 示:

 


 

                     图1

 

打开链接http://search.maven.org/#browse,就可以看到如图2所示的中央工厂的网页,

 


 

                      图2

 

在这个文本框中可以输入要寻找的jar包,比如log4j,找到一个1.2.17版本进入后,就可以看到如图2所示的页面:

 


 

                      图3

 

将红色区域复制后可以加到pom.xml中,Maven就可以将需要的jar文件下载到本地仓库了。

 

    二:

 

    在上节中,我们发现Maven的项目是按照一定的架构来编写的,目录结构都是固定的,也就是如果想使用Maven所带来的功能,就要遵守Maven所定义的规则,约定好了,配置就会减少,从而方便开发。

 

    在这里,将介绍Maven中mvn archetype:generate命令,来建立一个项目。

 

    比如在E:\Workspaces\STSWorkspace下建立Maven_02的项目,首先在控制台输入mvn archetype:generate命令,会发现Maven开始下载命令中需要的插件和jar文件了,如图4所示:

 


 

                         图4

 

然后等到下载一段时间后停止到如图5所示:

 


 

                       图5

 

然后回车就可以,出现选择版本,选择最新版本即可,如图6所示:

 


 

                      图6

 

然后选6后回车,然后填写groupId, artifactId,version,package(敲回车默认包),如图7所示:

 


 

                       图7

 

此时查看E:\Workspaces\STSWorkspace目录,会发现Maven_02项目已经成功构建了,如图8所示:

 


 

                         图8

 

由此可以看出通过Maven的命令mvn archetype:generate构建出来的框架是约定俗成的!

 

    注:也可以通过mvn archetype:generate -DgroupId=com.steven.maven -DrtifactId=Maven_02 -Dversion=0.0.1-SNAPSHOT创建一样的效果。

 

Eclipse项目构建

 

    在实际开发中都是会在项目工具中,如Eclipse中使用,下面将通过Eclipse工具,如果我们使用最原始的Eclipse作为开发工具,也就是说用 不带任何插件的Eclipse构建Maven项目,仍然需要下载插件m2eclipse,这里为了方便直接使用Spring Tool Suite(STS),下载地址为http://download.springsource.com/release/STS/3.4.0/dist/e4.3/spring-tool-suite-3.4.0.RELEASE-e4.3.1-win32.zip,已经带有Maven,下载后打开如图9所示:

 


 

                        图9

 

    然后打开后,做下面的操作,进行配置Maven

 

    首先选择Window->Preference找到左边侧边栏Maven选项,

 

    然后根据图示进行配置,选择本地解压后的Maven目录,点击确定,如图10所示:

 


 

                        图10

 

    然后选择本地仓库的位置,并完成配置,如图11,12所示:

 


 

                          图11

 


 

                        图12

 

    这样的话,Eclipse中就已经正确配置Maven了。接下来就可以使用Eclipse构建Maven项目:

 

    新建New->Other->Maven->Maven Project,如图13所示:

 


 

                     图13

 

    点击Next,默认Workspace,Next,然后选择quickstart模式,如图14所示:

 


 

                      图14

 

    点击Next,填入信息,如图15所示:

 


 

                  图15

 

    比如建议一个用户管理项目,填写以上的信息,然后点击Finish,完成项目的创建,此时如图16所示:

 


 

       图16

 

    此时通过Eclipse构建的Maven项目已经成功了,如果想进行测试,可以通过如图17所示的方法进行测试:

 


 

                     图17

 

    测试结果可以通过控制台查看:

 

 

 

  1. [INFO] Scanning for projects...  
  2. [INFO]                                                                           
  3. [INFO] ------------------------------------------------------------------------  
  4. [INFO] Building user-core 0.0.1-SNAPSHOT  
  5. [INFO] ------------------------------------------------------------------------  
  6. [INFO]   
  7. [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ user-core ---  
  8. [INFO] Using 'UTF-8' encoding to copy filtered resources.  
  9. [INFO] skip non existing resourceDirectory E:\Workspaces\STSWorkspace\user-core\src\main\resources  
  10. [INFO]   
  11. [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ user-core ---  
  12. [INFO] Nothing to compile - all classes are up to date  
  13. [INFO]   
  14. [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ user-core ---  
  15. [INFO] Using 'UTF-8' encoding to copy filtered resources.  
  16. [INFO] skip non existing resourceDirectory E:\Workspaces\STSWorkspace\user-core\src\test\resources  
  17. [INFO]   
  18. [INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ user-core ---  
  19. [INFO] Nothing to compile - all classes are up to date  
  20. [INFO]   
  21. [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ user-core ---  
  22. [INFO] Surefire report directory: E:\Workspaces\STSWorkspace\user-core\target\surefire-reports  
  23.   
  24. -------------------------------------------------------  
  25.  T E S T S  
  26. -------------------------------------------------------  
  27. Running com.steven.entity.AppTest  
  28. Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.044 sec  
  29.   
  30. Results :  
  31.   
  32. Tests run: 1, Failures: 0, Errors: 0, Skipped: 0  
  33.   
  34. [INFO] ------------------------------------------------------------------------  
  35. [INFO] BUILD SUCCESS  
  36. [INFO] ------------------------------------------------------------------------  
  37. [INFO] Total time: 8.959s  
  38. [INFO] Finished at: Sat Jan 18 23:47:29 CST 2014  
  39. [INFO] Final Memory: 6M/15M  
  40. [INFO] ------------------------------------------------------------------------  

      注:至此,Eclipse已经成功构建Maven项目,会发现通过工具会减少很多操作,项目的开发仍旧按照此架构进行,在接下来的博文中将会通过项目来讲解Maven的功能。

    在此恭祝大家学习愉快!

 

三. Maven的依赖管理特性

 

前情回顾

 

    在上一节中介绍了通过工具eclipse构建了maven项目,并且仅仅做了简单的运行演示,本节将通过eclipse构建出一个项目中的几个模块,并且通过这几个模块的联系讲解maven中依赖的特性。

 

项目构建

 

    本章通过一个典型的项目构建过程来学习Maven的依赖传递性。

 

    项目获取地址http://download.csdn.net/detail/songdeitao/6927445

 

    总共分为三个模块的项目编写user-core,user-log,user-service,在user-core中主要实现基本的实体类,初始文 件,dao的编写,在user-log中简单模拟日志文件的记录,在user-service模块中主要引入前两个模块,从而进行编写service模块 的功能,在这里模块的编写不是重点,这些都会给出代码,然而进行Maven依赖与传递的讲解才是重点,所以很多时候代码都是为了演示出效果,和实际开发还是有些差别,但所指代的思想是项目中所存在的。

 

普通依赖

 

    Maven的依赖是使用Maven坐标来定位的,而Maven坐标主要由GAV(groupId, artifactId, version)构成,因此,使用任何一个依赖之间,你都需要知道它的Maven坐标,在之前的第二章节中,从引入了Maven的中央工厂的网页,在此引入一个常用的Maven搜索jar包的资源库网页http://www.mvnrepository.com/,在此可以查找所需要的jar文件的GAV,比如在本文的第一章节的如下配置:

 

  1. <span style="font-family:KaiTi_GB2312;font-size:18px;"><dependency>  
  2.     <groupId>junit</groupId>  
  3.     <artifactId>junit</artifactId>  
  4.     <version>4.10</version>  
  5. </dependency></span>  

 

    可以通过如下列图所示的步骤进行查找到,而且以后的jar包查找过程都是按照此步骤进行获取,然后复制到pom.xml<dependencies>元素下,Maven就能在本地或者远程仓库中找到对应的jar包(不一定可以找到所有的jar文件)

 

 

                        图1

 

 

                        图2

 


 

                         图3

    此配置声明了一个对junit的依赖,它的groupId是junit, artifactId是junit, version是4.10。这一组GAV构成了一个Maven坐标,基于此,Maven就能在本地或者远程仓库中找到对应的junit-4.10.jar 文件。

传递依赖

 

一:

 

首先紧跟第二章节的新建项目构建出如下图所示的结构图,

 


 

          图4

 

通过此模块的构建,主要说明Maven的一下几个问题

 

    1、目录结构的默认构建,比如资源文件的src/main/resources目录的构建

 

    2、pom.xml文件的使用到的jar包的引入,比如在user-core中的文件内容如下所示:

 

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.   
  5.     <groupId>com.steven.user</groupId>  
  6.     <artifactId>user-core</artifactId>  
  7.     <version>0.0.1-SNAPSHOT</version>  
  8.     <packaging>jar</packaging>  
  9.   
  10.     <name>user-core</name>  
  11.     <url>http://maven.apache.org</url>  
  12.   
  13.     <properties>  
  14.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  15.     </properties>  
  16.   
  17.     <dependencies>  
  18.         <dependency>  
  19.             <groupId>junit</groupId>  
  20.             <artifactId>junit</artifactId>  
  21.             <version>4.10</version>  
  22.             <scope>test</scope>  
  23.         </dependency>  
  24.   
  25.         <dependency>  
  26.             <groupId>log4j</groupId>  
  27.             <artifactId>log4j</artifactId>  
  28.             <version>1.2.14</version>  
  29.         </dependency>  
  30.   
  31.         <dependency>  
  32.             <groupId>org.hibernate</groupId>  
  33.             <artifactId>hibernate-core</artifactId>  
  34.             <version>4.1.1.Final</version>  
  35.         </dependency>  
  36.   
  37.         <dependency>  
  38.             <groupId>mysql</groupId>  
  39.             <artifactId>mysql-connector-java</artifactId>  
  40.             <version>5.1.8</version>  
  41.         </dependency>  
  42.   
  43.   
  44.     </dependencies>  
  45. </project>  

            通过资源库中查找到相应的jar包,放到pom.xml中之后,Eclipse就会自动会和本地资源库或者远程仓库中进行匹配,如果本地中没有,就会通过网络下载从远程仓库中下载到本地仓库中。

    3、进行Maven项目模块的打包和加入到本地资源库的命令,如图所示

 


 

                    图5

 

    这样就可以执行打包或者将打包后的jar添加到本地仓库中。

 

二:

 

接着引入user-log,user-service

 


 

           图6                            图7

 

其中user-log的pom.xml如下所示

 

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.   
  5.     <groupId>com.steven.user</groupId>  
  6.     <artifactId>user-log</artifactId>  
  7.     <version>0.0.1-SNAPSHOT</version>  
  8.     <packaging>jar</packaging>  
  9.   
  10.     <name>user-log</name>  
  11.     <url>http://maven.apache.org</url>  
  12.   
  13.     <properties>  
  14.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  15.     </properties>  
  16.   
  17.     <dependencies>  
  18.         <dependency>  
  19.             <groupId>junit</groupId>  
  20.             <artifactId>junit</artifactId>  
  21.             <version>4.10</version>  
  22.             <scope>test</scope>  
  23.         </dependency>  
  24.   
  25.         <dependency>  
  26.             <groupId>dom4j</groupId>  
  27.             <artifactId>dom4j</artifactId>  
  28.             <version>1.5</version>  
  29.         </dependency>  
  30.         <dependency>  
  31.             <groupId>log4j</groupId>  
  32.             <artifactId>log4j</artifactId>  
  33.             <version>1.2.4</version>  
  34.         </dependency>  
  35.     </dependencies>  
  36. </project>  

    其中user-service的pom.xml如下所示

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.   
  5.     <groupId>com.steven.user</groupId>  
  6.     <artifactId>user-service</artifactId>  
  7.     <version>0.0.1-SNAPSHOT</version>  
  8.     <packaging>jar</packaging>  
  9.   
  10.     <name>user-service</name>  
  11.     <url>http://maven.apache.org</url>  
  12.   
  13.     <properties>  
  14.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  15.     </properties>  
  16.   
  17.     <dependencies>  
  18.         <dependency>  
  19.             <groupId>junit</groupId>  
  20.             <artifactId>junit</artifactId>  
  21.             <version>4.10</version>  
  22.             <scope>test</scope>  
  23.         </dependency>  
  24.         <dependency>  
  25.             <groupId>${project.groupId}</groupId>  
  26.             <artifactId>user-log</artifactId>  
  27.             <version>${project.version}</version>  
  28.         </dependency>  
  29.           
  30.         <dependency>  
  31.             <groupId>${project.groupId}</groupId>  
  32.             <artifactId>user-core</artifactId>  
  33.             <version>${project.version}</version>  
  34.         </dependency>  
  35.           
  36.     </dependencies>  
  37. </project>  

 

    此时细心的读者会发现在user-service的pom文件中出现${project.groupId}和${project.version}的写法,这是Maven的内置隐式变量,常用的如下介绍:

 

${basedir} 项目根目录
${project.build.directory} 构建目录,缺省为target
${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes
${project.build.finalName} 产出物名称,缺省为${project.artifactId}-${project.version}
${project.packaging} 打包类型,缺省为jar
${project.xxx} 当前pom文件的任意节点的内容(这里所使用到的)

 

注意:

 

    在完成user-service对user-log和user-service模块的jar包引入的时候,一定要将这两个模块进行install处理,这样在user-service中才可以访问到前两个模块的jar包。

 

传递依赖

 

此时打开user-service的pom的dependency  hierarchy图,如图所示:

 


 

                      图8

 

    会发现在user-log中使用log4j-1.2.4.jar而user-core中使用log4j-1.2.14.jar,但user-service包含user-log和user-core后,所使用的是log4j-1.2.4,为什么不使用新的版本呢?

 

    这是因为我在user-service中将user-log写在了user-core前面。但难道谁写在前面就在前面了吗?

 

    那我就将这两个配置调换一下,得到的图如图9所示

 


 

                     图9

 

    再看log4j变成了log4j-1.2.14.jar(图中没有标出,但不难看出),那确实是这样吗?然后看图8中dom4j是1.5版本,在图9中调换过位置后还是1.5版本,怎么回事?细心的读者会发现log4j是出于user-core和user-log的同一级别,而dom4j在user-core和user-log却不是在同一级别。

 

奥,我明白了,原来是这么一回事:

 

结论:

 

1、当依赖的级别相同时,引入最先导入的jar包

 

2、当依赖级别不同时候,引入级别最近的jar包

 

那我偏要使用dom4j1.6.1的版本,那怎么办呢?

 

排除依赖

 

    Maven很智能,在此提供一个元素,exclusion,只要在不想要的模块中添加此元素,比如不想要user-log的dom4j1.5版本,则只要在user-service中这样编写即可:

 

 

 

  1. <dependency>  
  2.             <groupId>${project.groupId}</groupId>  
  3.             <artifactId>user-log</artifactId>  
  4.             <version>${project.version}</version>  
  5.             <exclusions>  
  6.                 <exclusion>  
  7.                     <groupId>dom4j</groupId>  
  8.                     <artifactId>dom4j</artifactId>  
  9.                 </exclusion>  
  10.             </exclusions>  
  11.         </dependency>  

            此时在查看user-service的pom的dependency  hierarchy图,发现已经成功使用dom4j1.6.1版本了,如图所示


 

                     图10

 

依赖范围(scope)

 

    读者还会发现,在图8,9,10中,每个jar后都有类似[compile]的标识,这是什么意思呢?这里将引入Maven的依赖范围概念。

 

    什么是依赖范围呢?

 

    引入:

 

    Maven在编译主代码的时候需要使用一套classpath,在编译和执行测试的时候会使用另一套classpath,实际运行项目的时候,又会使用一套classpath。
    依赖范围就是用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系,

 

    Maven有以下几种依赖范围:
    compile: 编译依赖范围。

 

    如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。
 
    test: 测试依赖范围。

 

    使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子就是JUnit, 它只有在编译测试代码及运行测试的时候才需要。这也是本文的pom文件中为何junit的scope是使用test范围的原因。
 
    provided: 已提供依赖范围。

 

    使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍。
 
    runtime: 运行时依赖范围。

 

使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。

 

   

 

    注意:以上四种范围是开发中常用的配置,而以下两种都是不要求的,使用的很少,了解即可

 

    system: 系统依赖范围。

 

该依赖与三种 classpath的关系,和provided依赖范围完全一致。但是,使用system范围依赖时必须通过systemPath元素显式地指定依赖文件 的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。

 

    import(Maven 2.0.9及以上): 导入依赖范围。

 

总结

 

    至此,对于Maven的依赖性已经讲解差不多了,余下的在开发中很少使用到,所以掌握以上内容已经足够使用了,而且Maven的依赖算是Maven的学习中的一个难点,因此需要自己手动创建项目进行测试验证。

 

    在此,一样恭祝大家学习愉快,新年快乐!

 

四. Maven聚合和继承

 

前情回顾

 

    在上一章节中,通过三个模块的项目开发,讲解了Maven依赖管理的特性,从而对Maven依赖的表现,范围等有着一定的认识,但每次对一个模块进行更 改,都要将对应模块进行test或者package或者install的操作后,使用到该模块的项目才可以使用,这样的操作有些繁琐,如果有过多的模块, 那将需要执行多次的操作,还有,在每个模块pom.xml文件中,存在很多之前模块相同的依赖包,并且以后开发时候还会有很多相同的常量。

 

问题引出

 

    能不能执行一次命令就可以完成对每个模块的操作?(Maven的聚合)

 

    能不能不要在每个模块中都要定义相同的依赖包或者重复的元素呢?(Maven的继承)

 

聚合和继承的实现

 

    在实现过程中,将继续使用上一个章节构建的项目模块,并在上进行更改,如果没有项目概念的,可以参考上一章节的讲解,构建相应的项目。

 

    聚合继承的操作只要在项目模块的目录中创建实现的pom.xml文件,然后在pom.xml文件中定义相应的操作即可,如下图所示

 


 

                     图1

 

    但在这里我们可以通过Eclipse构建pom.xml文件(可以同时进行聚合和继承的操作),可以通过以下步骤

 


 

                         图2

 


 

                       图3

 


 

                          图4

 

    然后生成pom.xml文件

 


 

                          图5

 

    此时聚合的实现,只要在pom.xml中添加聚合的模块即可,实现的操作如下所示:

 

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>com.steven.user</groupId>  
  5.     <artifactId>user-parent</artifactId>  
  6.     <version>0.0.1-SNAPSHOT</version>  
  7.     <packaging>pom</packaging>  
  8.       
  9.     <modules>  
  10.         <module>../user-core</module>  
  11.         <module>../user-log</module>  
  12.         <module>../user-service</module>  
  13.     </modules>  
  14.       
  15. </project>  

注意:

    这里的<module>模块中../是指代上一级目录,因为在Eclipse中需要指向上一级才可以引入相应的模块。
    这时候,对parent模块执行clean操作,会发现其包含的每个模块都已经执行了操作,

 

 

 

  1. [INFO] Scanning for projects...  
  2. [INFO] ------------------------------------------------------------------------  
  3. [INFO] Reactor Build Order:  
  4. [INFO]   
  5. [INFO] user-core  
  6. [INFO] user-log  
  7. [INFO] user-service  
  8. [INFO] user-parent  
  9. [INFO]                                                                           
  10. [INFO] ------------------------------------------------------------------------  
  11. [INFO] Building user-core 0.0.1-SNAPSHOT  
  12. [INFO] ------------------------------------------------------------------------  
  13. [INFO]   
  14. [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ user-core ---  
  15. [INFO] Deleting E:\Workspaces\STSWorkspace\user-core\target  
  16. [INFO]                                                                           
  17. [INFO] ------------------------------------------------------------------------  
  18. [INFO] Building user-log 0.0.1-SNAPSHOT  
  19. [INFO] ------------------------------------------------------------------------  
  20. [INFO]   
  21. [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ user-log ---  
  22. [INFO] Deleting E:\Workspaces\STSWorkspace\user-log\target  
  23. [INFO]                                                                           
  24. [INFO] ------------------------------------------------------------------------  
  25. [INFO] Building user-service 0.0.1-SNAPSHOT  
  26. [INFO] ------------------------------------------------------------------------  
  27. [INFO]   
  28. [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ user-service ---  
  29. [INFO] Deleting E:\Workspaces\STSWorkspace\user-service\target  
  30. [INFO]                                                                           
  31. [INFO] ------------------------------------------------------------------------  
  32. [INFO] Building user-parent 0.0.1-SNAPSHOT  
  33. [INFO] ------------------------------------------------------------------------  
  34. [INFO]   
  35. [INFO] ---<span style="color:#ff0000;"> maven-clean-plugin:2.5:clean (default-clean) @ user-parent </span>---  
  36. [INFO] ------------------------------------------------------------------------  
  37. [INFO] Reactor Summary:  
  38. [INFO]   
  39. [INFO] <span style="color:#ff0000;">user-core</span> ......................................... SUCCESS [0.255s]  
  40. [INFO] <span style="color:#ff0000;">user-log</span> .......................................... SUCCESS [0.014s]  
  41. [INFO] <span style="color:#ff0000;">user-service</span> ...................................... SUCCESS [0.015s]  
  42. [INFO] user-parent ....................................... SUCCESS [0.002s]  
  43. [INFO] ------------------------------------------------------------------------  
  44. [INFO] BUILD SUCCESS  
  45. [INFO] ------------------------------------------------------------------------  
  46. [INFO] Total time: 0.500s  
  47. [INFO] Finished at: Mon Feb 17 21:21:50 CST 2014  
  48. [INFO] Final Memory: 4M/15M  
  49. [INFO] ------------------------------------------------------------------------  

    下面进行继承的操作,继承的操作在这里主要对依赖和常量进行配置,配置后的pom文件依次是

user-parent中pom.xml

 

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>com.steven.user</groupId>  
  5.     <artifactId>user-parent</artifactId>  
  6.     <version>0.0.1-SNAPSHOT</version>  
  7.     <packaging>pom</packaging>  
  8.   
  9.     <modules>  
  10.         <module>../user-core</module>  
  11.         <module>../user-log</module>  
  12.         <module>../user-service</module>  
  13.     </modules>  
  14.   
  15.     <url>http://maven.apache.org</url>  
  16.   
  17.     <properties>  
  18.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  19.     </properties>  
  20.   
  21.     <dependencyManagement>  
  22.         <dependencies>  
  23.             <dependency>  
  24.                 <groupId>junit</groupId>  
  25.                 <artifactId>junit</artifactId>  
  26.                 <version>4.10</version>  
  27.                 <scope>test</scope>  
  28.             </dependency>  
  29.   
  30.             <dependency>  
  31.                 <groupId>log4j</groupId>  
  32.                 <artifactId>log4j</artifactId>  
  33.                 <version>1.2.14</version>  
  34.             </dependency>  
  35.             <dependency>  
  36.                 <groupId>org.hibernate</groupId>  
  37.                 <artifactId>hibernate-core</artifactId>  
  38.                 <version>4.1.1.Final</version>  
  39.             </dependency>  
  40.   
  41.             <dependency>  
  42.                 <groupId>mysql</groupId>  
  43.                 <artifactId>mysql-connector-java</artifactId>  
  44.                 <version>5.1.8</version>  
  45.             </dependency>  
  46.   
  47.             <dependency>  
  48.                 <groupId>dom4j</groupId>  
  49.                 <artifactId>dom4j</artifactId>  
  50.                 <version>1.5</version>  
  51.             </dependency>  
  52.   
  53.             <dependency>  
  54.                 <groupId>${project.groupId}</groupId>  
  55.                 <artifactId>user-core</artifactId>  
  56.                 <version>${project.version}</version>  
  57.             </dependency>  
  58.   
  59.             <dependency>  
  60.                 <groupId>${project.groupId}</groupId>  
  61.                 <artifactId>user-log</artifactId>  
  62.                 <version>${project.version}</version>  
  63.                 <exclusions>  
  64.                     <exclusion>  
  65.                         <groupId>dom4j</groupId>  
  66.                         <artifactId>dom4j</artifactId>  
  67.                     </exclusion>  
  68.                 </exclusions>  
  69.             </dependency>  
  70.   
  71.         </dependencies>  
  72.     </dependencyManagement>  
  73. </project>  

 

user-core中pom.xml

 

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.   
  5.     <parent>  
  6.         <groupId>com.steven.user</groupId>  
  7.         <artifactId>user-parent</artifactId>  
  8.         <version>0.0.1-SNAPSHOT</version>  
  9.         <relativePath>../user-parent/pom.xml</relativePath>  
  10.     </parent>  
  11.   
  12.     <artifactId>user-core</artifactId>  
  13.     <packaging>jar</packaging>  
  14.   
  15.     <name>user-core</name>  
  16.   
  17.     <dependencies>  
  18.         <dependency>  
  19.             <groupId>junit</groupId>  
  20.             <artifactId>junit</artifactId>  
  21.         </dependency>  
  22.   
  23.         <dependency>  
  24.             <groupId>log4j</groupId>  
  25.             <artifactId>log4j</artifactId>  
  26.         </dependency>  
  27.   
  28.         <dependency>  
  29.             <groupId>org.hibernate</groupId>  
  30.             <artifactId>hibernate-core</artifactId>  
  31.         </dependency>  
  32.   
  33.         <dependency>  
  34.             <groupId>mysql</groupId>  
  35.             <artifactId>mysql-connector-java</artifactId>  
  36.         </dependency>  
  37.     </dependencies>  
  38. </project>  

 

user-log中pom.xml

 

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <parent>  
  5.         <groupId>com.steven.user</groupId>  
  6.         <artifactId>user-parent</artifactId>  
  7.         <version>0.0.1-SNAPSHOT</version>  
  8.         <relativePath>../user-parent/pom.xml</relativePath>  
  9.     </parent>  
  10.     <artifactId>user-log</artifactId>  
  11.     <packaging>jar</packaging>  
  12.   
  13.     <name>user-log</name>  
  14.   
  15.     <dependencies>  
  16.         <dependency>  
  17.             <groupId>junit</groupId>  
  18.             <artifactId>junit</artifactId>  
  19.         </dependency>  
  20.   
  21.         <dependency>  
  22.             <groupId>dom4j</groupId>  
  23.             <artifactId>dom4j</artifactId>  
  24.         </dependency>  
  25.         <dependency>  
  26.             <groupId>log4j</groupId>  
  27.             <artifactId>log4j</artifactId>  
  28.         </dependency>  
  29.     </dependencies>  
  30. </project>  

 

user-service中pom.xml

 

 

 

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <parent>  
  5.         <groupId>com.steven.user</groupId>  
  6.         <artifactId>user-parent</artifactId>  
  7.         <version>0.0.1-SNAPSHOT</version>  
  8.         <relativePath>../user-parent/pom.xml</relativePath>  
  9.     </parent>  
  10.     <artifactId>user-service</artifactId>  
  11.     <packaging>jar</packaging>  
  12.   
  13.     <name>user-service</name>  
  14.   
  15.     <dependencies>  
  16.         <dependency>  
  17.             <groupId>junit</groupId>  
  18.             <artifactId>junit</artifactId>  
  19.         </dependency>  
  20.   
  21.   
  22.         <dependency>  
  23.             <groupId>${project.groupId}</groupId>  
  24.             <artifactId>user-core</artifactId>  
  25.         </dependency>  
  26.   
  27.         <dependency>  
  28.             <groupId>${project.groupId}</groupId>  
  29.             <artifactId>user-log</artifactId>  
  30.         </dependency>  
  31.   
  32.     </dependencies>  
  33. </project>  

    此时即可完成继承的操作,会发现user-core,user-log,user-service中版本号,依赖范围,排除依赖都不需要写了,只要都写在父文件中就可以了,这样就减少了很多重复代码的编写了。

总结

 

    此时就可以通过父类user-parent执行聚合继承操作后,对其他模块进行统一管理,这里有几个提示点:

 

    1、通过聚合就可以共同操作,通过继承就可以解决jar冲突,排除依赖一样可以写在父文件中,

 

    2、在Eclipse中进行对模块依赖的控制,可以先将一个模块的所有依赖放到父文件的<dependencyManagement>节点 下,然后在该模块中Eclipse会有重复的提示,删除重复行即可,然后在其他模块中先对重复行进行删除,对父文件中没有的依赖进行拷贝。

 

    在此预祝大家学习愉快!有任何错误或者问题可以提出,在此不胜感激!

 

五. Maven仓库管理器之初识Nexus

 

认识Nexus

 

    Nexus是Maven的最常用的仓库管理器,可以认为是Maven的私服,通过此可以免去自己(本地仓库)直接去购买游戏提供商的服务(Maven的中 央仓库),减少费用开支(带宽和时间等)。同时,Nexus提供强大的仓库管理功能,友好的操作界面,占用内存小等优势已经让Nexus成为主流的 Maven仓库管理器。

 

为什么要构建Nexus

 

    大家可以考虑一下,在实际的开发中,我们不可能是自己开发(如果这样,我只能说Maven可以不需要使用了),而且在多人多个模块开发的时候,我们构建的 Maven项目,总会有一个模块需要另一个模块的依赖,或者有相同的jar包,当然,我们可以通过svn这样的工具进行同步,但这样不断进行同步,会增加 开发的复杂度;

 

    再一个,开发中,如果新增加一个开发者,那么当他将项目构建时候,或许会根据pom文件从中央仓库中下载大量的jar包,会造成网络问题,同时,当一直访问同一个地址,有可能被认为是攻击,还有,如果外网断掉了,这样会造成业务中断。

 

获取和使用

 

    打开连接http://www.sonatype.org/downloads/nexus-latest-bundle.zip,Nexus提供了两种使用方式,刚下载的就是内嵌服务器jetty的方式,只要你有JRE就能直接运行,第二种方式是WAR包,需要将其发布到web容器比如tomcat中才可以。

 

    注:下载后有可能会比文中使用的版本要新,但都是一样的操作。

 

    下载完后,进行解压,解压后会发现有两个文件夹,如图1所示:

 


 

              图1

 

    第一个文件夹中是Nexus的一些控制文件,类似于tomcat中的结构,第二个文件夹主要是用来存放从中央仓库中下载的jar等文件。

 

    将E:\StudySoftware\javaEE\nexus-2.7.2-03-bundle\nexus-2.7.2-03\bin添加到环境变量中(为了在命令控制台总可以很好的操作),如图2所示

 


 

                      图2

 

    接下来,打开命令控制台,输入nexus,即可显示如图3信息

 


 

                        图3

 

    这个表示Nexus环境变量配置成功,下面进行配置E:\StudySoftware\javaEE\nexus-2.7.2-03-bundle\nexus-2.7.2-03\bin\jsw\conf\wrapper.conf文件,做如下修改(如果有配置过JRE路径可以不需要此项配置)

 


 

                         图4

 


 

                        图5

 

    然后执行如下操作nexus install:

 


 

                       图6

 

    会发现安装成功,但有时会出现以下问题,wrapper | OpenSCManager failed问题,如图7所示:

 


 

                      图7

 

    问题是命令控制台没有按管理员权限打开,即没有权限,解决方法就是将命令控制台以管理员的方式打开,如图8所示进行设置:

 


 

                         图8

 

    这样打开后既可和图6的执行效果一样。

 

    刚刚执行过nexus install命令,即将nexus的服务安装到windows的服务中,下面我们启动服务。

 

    方法一:

 

    我们可以通过windows中的服务查看,如图9所示(可以通过系统键+R,然后输入services.msc回车即可出现图示)

 


 

                     图9

 

    方法二:

 


 

    这两种方法都可以进行服务启动。

 

    检验:

 

    下面可以在浏览器中输入地址http://localhost:8081/nexus/index.html进行打开Nexus的UI界面(如果是装在其他电脑上的,则需要换成电脑的准确IP地址,而我只是作为讲解,装在自己的电脑上了(哎!悲催的电脑,都快吃不消了,以后有钱一定换个好的!))

 


 

                       图11

 

    这是打开后的页面,下面点击右上角的Log in,用户名为admin,密码默认为admin123,如图12所示:

 


 

                     图12

 

    登录成功后如图13所示:

 


 

                        图13

 

    登录成功后,下面就将进行Nexus的配置,以及讲解Nexus的仓库管理功能,由于篇幅问题,或者写的确实有些详细了,然后打算通过再一次讲解具体的Nexus的使用过程。

 

    在此恭祝大家学习愉快!

 

六. Maven仓库管理器之应用Nexus

 

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

 

Nexus-私有仓库的配置

 

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

 


 

                        图14

 

    在这里:

 

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

 

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

 


 

                       图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文件中,定义了中央仓库的位置,配置文件如下所示

 

 

 

  1. ………………………………………………………………  
  2. <repositories>  
  3. <repository>  
  4.   <id>central</id>  
  5.   <name>Central Repository</name>  
  6.   <url>http://repo.maven.apache.org/maven2</url>  
  7.   <layout>default</layout>  
  8.   <snapshots>  
  9.     <enabled>false</enabled>  
  10.   </snapshots>  
  11. </repository>  
  12. </repositories>  
  13. ………………………………………………………………  

    其中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),配置如下:

 

 

 

  1. …………………………………………  
  2.  <profiles>  
  3.    <profile>  
  4.     <id>nexusProFile</id>  
  5.     <repositories>  
  6.       <repository>  
  7.         <id>localNexus</id>  
  8.     <name>Nexus Repository</name>  
  9.         <url>http://localhost:8081/nexus/content/groups/public/</url>  
  10.         <releases>  
  11.           <enabled>true</enabled>  
  12.         </releases>  
  13.         <snapshots>  
  14.       <!-- 此选项默认是关闭的,手动打开 -->  
  15.           <enabled>true</enabled>  
  16.         </snapshots>  
  17.       </repository>  
  18.      </repositories>  
  19.    </profile>  
  20.   </profiles>  
  21.   <activeProfiles>  
  22.     <!-- 激活上面的配置 -->  
  23.     <activeProfile>nexusProFile</activeProfile>  
  24.   </activeProfiles>  
  25. …………………………………………  

      Maven中的profile是一组可选的配置,可以用来设置或者覆盖配置默认值。有了profile,你就可以为不同的环境定制构建。  
    这个时候,做个试验,可以在user-core的pom.xml中加入以下依赖(这个依赖包并不存在于本地或者Nexus仓库中)

  1. <dependency>  
  2.    <groupId>org.mybatis</groupId>  
  3.    <artifactId>mybatis</artifactId>  
  4.    <version>3.1.1</version>  
  5. </dependency>  

    添加好后进行保存,会发现Eclipse的控制台中有如图16的信息:

                       图16

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

 

                    图17

 

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

 

                   图18

 

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

 

 

 

  1. <dependency>  
  2.     <groupId>org.springframework</groupId>  
  3.     <artifactId>spring-core</artifactId>  
  4.     <version>3.2.2.RELEASE</version>  
  5. </dependency>  

这个时候在Eclipse中点击保存,会发现如下的信息

  1. 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.  
  2. 14-3-7 GMT+0800下午8:29:42: [INFO] Number of application's worked threads is 4  
  3. 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  
  4. 14-3-7 GMT+0800下午8:29:44: [INFO] Number of application's worked threads is 4  
  5. 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  
  6. 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  
  7. ………………………………………………………………………………  

      首先通过Nexus下载,但服务已经关闭,这个时候仍然可以下载,而且通过中央仓库进行下载。但在项目中,不允许本地仓库直接下载中央仓库的依赖包,这个时候就需要进行对中央仓库进行覆盖,使之只能通过Nexus访问中央仓库,这个时候需要对镜像进行配置。

在settings.xml中配置镜像

 

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

 

 

 

  1. …………………………………………………………  
  2. <mirror>  
  3.   <id>nexusMirror</id>  
  4.   <mirrorOf>*</mirrorOf>  
  5.   <name>Human Readable Name for this Mirror.</name>  
  6.   <url>http://localhost:8081/nexus/content/groups/public/</url>  
  7. </mirror>  
  8. …………………………………………………………  

    这里的*号代表所有的仓库都是通过这个url地址访问,这个时候可以附加一段配置,原来的中央仓库中snapshots版本的依赖包默认是不可以下载的,但可以通过以下配置进行修改

 

 

  1. ……………………………………  
  2. </profiles>  
  3.  ……………………………………  
  4.  <profile>  
  5.    <id>centralProFile</id>  
  6.    <repositories>  
  7.      <repository>  
  8.     <id>central</id>  
  9.     <name>Central Repository</name>  
  10.     <!--由于配置过镜像,这个url不起作用-->  
  11.     <url>http://repo.maven.apache.org/maven2</url>  
  12.     <layout>default</layout>  
  13.     <snapshots>  
  14.       <!--覆盖中央仓库中的false配置,可以从中央仓库中下载snapshot版本-->  
  15.       <enabled>true</enabled>  
  16.     </snapshots>  
  17.   </repository>  
  18.     </repositories>  
  19.   </profile>  
  20.   
  21.  </profiles>  
  22.  <activeProfiles>  
  23.    <!-- 激活上面的配置 -->  
  24.    <activeProfile>centralProFile</activeProfile>  
  25.  </activeProfiles>  
  26.  ……………………………………  

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

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

 

 

 

  1. <dependency>  
  2.     <groupId>org.mortbay.jetty</groupId>  
  3.     <artifactId>jetty</artifactId>  
  4.     <version>6.1.26</version>  
  5. </dependency>  

跟刚才的步骤一样,但此时保存后,Eclipse控制台中的信息如下所示:

  1. 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  
  2. 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.  
  3. 14-3-7 GMT+0800下午9:13:58: [INFO] Number of application's worked threads is 4  
  4. 14-3-7 GMT+0800下午9:14:02: [INFO] Using 'UTF-8' encoding to copy filtered resources.  
  5. 14-3-7 GMT+0800下午9:14:02: [INFO] skip non existing resourceDirectory E:\Workspaces\STSWorkspace\user-service\src\main\resources  
  6. 14-3-7 GMT+0800下午9:14:02: [INFO] Using 'UTF-8' encoding to copy filtered resources.  
  7. 14-3-7 GMT+0800下午9:14:02: [INFO] skip non existing resourceDirectory E:\Workspaces\STSWorkspace\user-service\src\test\resources  

          这里只能通过Nexus下载依赖包,但是由于服务停止,所以下载失败,而如果此时将服务打开


                     图19

 

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

 

 

 

  1. 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  
  2. 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  

    但此时可能出现以下问题

  1. [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所示

                      图20

 

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

 

    思路2:

 

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

 

 

 

  1. 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本地库的哪个仓库中,具体如下所示:

 

 

 

  1. ………………………………………………………………  
  2. <distributionManagement>  
  3.     <repository>  
  4.         <id>user-core-release</id>  
  5.         <name>user core release</name>  
  6.         <url>http://localhost:8081/nexus/content/repositories/releases/</url>  
  7.     </repository>  
  8.     <snapshotRepository>  
  9.         <id>user-core-snapshot</id>  
  10.         <name>user core snapshot</name>  
  11.         <url>http://localhost:8081/nexus/content/repositories/snapshots/</url>  
  12.     </snapshotRepository>  
  13. </distributionManagement>  
  14. ………………………………………………………………  


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


 

                       图21

 

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

 

 

 

  1. ………………………………………………………………  
  2. <server>  
  3.       <id>user-core-release</id>  
  4.       <username>deployment</username>  
  5.       <password>deployment123</password>  
  6. </server>  
  7. <server>  
  8.       <id>user-core-snapshot</id>  
  9.       <username>deployment</username>  
  10.       <password>deployment123</password>  
  11. </server>  
  12. ………………………………………………………………  


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


 

                         图22

 

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

 


 

                   图23

 

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

 

通过Nexus搜索构件

 

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

 

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

 

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

 

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

 

    如图所示:

 


 

                       图24

 

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

 

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

 

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

 


 

                       图25

 

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

 

创建本地仓库并设置权限

 

创建仓库

 

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

 


 

                       图26

 

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

 


 

                     图27

 

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

 


 

                        图28

 

创建权限

 

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

 


 

                      图29

 

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

 


 

                     图30

 

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

 


 

                       图31

 

创建角色

 

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

 

    如图32,创建角色

 


 

                    图32

 

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

 


 

                      图33

 

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

 


 

                       图34

 

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

 


 

                          图35

 

创建用户

 

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

 


 

                        图36

 

    然后填入信息,如图所示

 


 

                      图37

 

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

 


 

                      图38

 

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

 


 

                      图39

 

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

 

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

 

 

 

  1. ………………………………………………………………  
  2. <distributionManagement>  
  3.     <repository>  
  4.         <id>user-core-release</id>  
  5.         <name>user core release</name>  
  6.         <url>http://localhost:8081/nexus/content/repositories/UserRelease/</url>  
  7.     </repository>  
  8.     <snapshotRepository>  
  9.         <id>user-core-snapshot</id>  
  10.         <name>user core snapshot</name>  
  11.         <url>http://localhost:8081/nexus/content/repositories/UserSnapshots/</url>  
  12.     </snapshotRepository>  
  13. </distributionManagement>  
  14. ………………………………………………………………  


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

 

 

  1. ………………………………………………………………  
  2. <server>  
  3.       <id>user-core-release</id>  
  4.       <username>UserRelease</username>  
  5.       <password>user123</password>  
  6. </server>  
  7. <server>  
  8.       <id>user-core-snapshot</id>  
  9.       <username>UserRelease</username>  
  10.       <password>user123</password>  
  11. </server>  
  12. ………………………………………………………………  


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

总结 

 

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

 

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

 

七. Maven中的生命周期与插件机制

Maven的生命周期

    就像人生一样,出生,成长,死亡,这个每个人乃至整个生命都拥有的特性。Maven的构造者就发现,整个项目的构建过程都拥有高度的相似性,清理、初 始化、编译、测试、打包、集成测试、验证、部署、站点发布等等,于是,Maven就在这些过程中抽象出三套执行机制,也就是独立的三种生命周期,分别是

  • Clean Lifecycle 项目的构建之前进行清理操作
  • Compile(Default) Lifecycle 主要进行项目构建的操作,编译测试打包部署等核心操作
  • Site Lifecycle 项目报告的生成,站点发布操作
完整生命周期(供参考)

1.Clean 
  pre-clean 执行一些清理前需要完成的工作。
  clean 清理上一次构建生成的文件
  post-clean 执行一些清理后需要完成的工作
2.Compile(Default) 
  validate 验证项目是正确的并且所有必需的信息都是可用的
  initialize 初始化构建状态
  generate-sources 产生所有的用来编译的源代码
  process-sources 处理源代码
  generate-resources 产生包含在package中的资源
  process-resources 复制和处理资源到目标目录,为打包做好准备
  compile 编译项目的主源代码
  process-classes 对编译器产生的文件进行后期处理
  generate-test-sources 产生所有用来编译的测试源代码
  process-test-sources 处理测试源代码
  generate-test-resources 创建测试所需要的资源
  process-test-resources 复制和处理资源到测试目标目录
  compile 编译测试源代码到目标目录
  process-test-classes 对编译测试源代码产生的文件进行后期处理
  test 使用适当的单元测试框架运行测试,这些测试代码不应该被打包或者部署
  prepare-package 执行所有需要执行的操作为打包做准备,这往往会产生一个还未打包的处理过的包版本
  package 使用设置的方式对编译过的文件进行打包
  pre-integration-test 执行一些集成测试执行前必须的操作
   integration-test 处理和部署包到集成测试环境中,进行测试
  post-integration-test 对集成测试进行后期处理
   verify 执行所有检查确保包是正确的和符合质量要求的
  install 将包安装至本地仓库,以让其它项目依赖
    deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享
3.Site 
  pre-site 前期准备
  site 产生项目的站点文档
  post-site 后期处理
  site-deploy 部署站点到服务器

插件机制

    虽然Maven生命周期中有这么多个执行过程,但这些都是一个抽象的概念,这个概念性的东西意味着它并不做任何实质性的事情,也就是说:它就像接口,只定 义规范,具体细节它不管。具体的 实现细节则交给了Maven 的各个丰富的插件,也就是说Maven的插件是要完全依赖于Maven的生命周期的,根据周期中的这些执行过程,才可以定义出相应功能的插件。

    因此Maven的生命周期和Maven插件是相辅相成的,只有周期,没有插件,Maven是没有法子执行相应的操作,只有插件,没有周期,插件将失去了意义,在这里,可以很好的赞叹Maven的开发者多么智慧的头脑,以及多好的设计原则。

    (待修改...)

 

posted @ 2015-09-16 14:01  wenlj2000  阅读(321)  评论(0编辑  收藏  举报