maven基础教程(二)

来源:互联网 发布:思途cms源码 编辑:程序博客网 时间:2024/06/06 09:08

在阅读该博客之前,建议点击阅读 《 maven基础教程(一) 》
本博客继续讲解maven的一些基础知识。

一、maven的生命周期和插件

完整的项目构建过程包括:清理、编译、测试、打包、集成测试、验证、部署,Maven从中抽取了一套完善的、易扩展的生命周期。Maven的生命周期是抽象的,其中的具体任务都交由插件来完成。

maven的生命周期分为3个部分:clean、default、site。三套生命周期相互独立且每个周期分别有多个阶段,但各个生命周期中的阶段却是有顺序的,且后面的阶段依赖于前面的阶段。执行某个阶段时,其前面的阶段会依顺序执行,但不会触发另外两套生命周期中的任何阶段。

1、clean:清理项目。
三个阶段:
pre-clean:执行清理前的工作;
clean:清理上一次构建生成的所有文件;
post-clean:执行清理后的文件;
2、default:构建项目(maven生命周期中最核心部分)
包含以下阶段:compile/test/package/install/deploy等阶段;
3、site:生成项目站点
根据pom文件自动生成站点,有以下几个阶段:
pre-site:在生成项目站点前要完成的工作
site:生成项目的站点文档
post-site:在生成项目站点后要完成的工作
site-deploy:发布生成的站点到服务器上
4、maven插件
Maven的核心文件很小,主要的任务都是由插件来完成。定位到:%本地仓库%\org\apache\maven\plugins,可以看到一些下载好的插件:
这里写图片描述
Maven的生命周期是抽象的,实际需要插件来完成任务,这一过程是通过将插件的目标(goal)绑定到生命周期的具体阶段(phase)来完成的。如:将maven-compiler-plugin插件的compile目标绑定到default生命周期的compile阶段,完成项目的源代码编译;

二、pom.xml和settings.xml详解

具体参考:
pom.xml配置详解:http://blog.csdn.net/jiana227/article/details/7690245
settings.xml配置详解:http://blog.csdn.net/uohzoaix/article/details/7035302

三、依赖范围

Maven因为执行一系列编译、测试和部署运行等操作,在不同的操作下使用的classpath不同,依赖范围就是用来控制依赖与三种 classpath(编译classpath、测试classpath、运行classpath)的关系。
Maven有以下几种依赖范围:

compile:编译依赖范围(默认),使用此依赖范围对于编译、测试、运行三种 classpath 都有效,即在编译、测试和运行的时候都要使用该依赖jar包;

test:测试依赖范围,从字面意思就可以知道此依赖范围只能用于测试classpath,而在编译和运行项目时无法使用此类依赖,典型的是JUnit,它只用于编译测试代码和运行测试代码的时候才需要;

provided:此依赖范围,对于编译和测试classpath有效,而对运行时无效;

runtime:运行时依赖范围,对于测试和运行classpath有效,但是在编译主代码时无效,典型的就是JDBC驱动实现;

system:系统依赖范围,使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径,不依赖Maven仓库解析,所以可能会造成建构的不可移植,谨慎使用;

import导入的范围,它只使用在dependencyManagement中,表示从其他的pom中导入dependecy的配置;

配置例子:

 <dependency>       <groupId>javax.sql</groupId>       <artifactId>jdbc-stdext</artifactId>       <version>2.0</version>       <scope>system</scope>       <systemPath>${java.home}/lib/rt.jar</systemPath>  </dependency> 

四、依赖传递

在古惑仔中,山鸡依赖于南哥,南哥依赖于B哥。此案例感谢慕课网。
1、一个项目中依赖另一个项目,需要在pom.xml中进行配置:
比如在南哥中添加依赖bi哥的配置

<dependency>      <groupId>com.hongxing</groupId>      <artifactId>biGe-project</artifactId>      <version>1.1.1</version>  </dependency> 

在编译南哥的项目时(添加了依赖于bi哥),此时bi哥项目需要进行install之后才可以被依赖,否则编译南哥项目不成功;
2、若在山鸡项目中进行依赖于南哥项目的配置(南哥已install),将会发现在山鸡项目中默认也依赖了bi哥的项目,这就是依赖的传递性;
3、山鸡也可以只依赖于南哥而不依赖于bi哥,这里就用到依赖排除,山鸡pom.xml中配置如下:

<dependency>      <groupId>com.hongxing</groupId>      <artifactId>nanGe-project</artifactId>      <version>1.1.1</version>    <exclusions>        <exclusion>            <!--被排除模块的坐标(bi哥坐标)-->            <groupId>xxx</groupId>            <artifactId>xxx</artifactId>        </exclusion>    </exclusions></dependency> 

这样保存pom.xml文件之后,山鸡项目将只依赖南哥而不依赖于bi哥了;

综上所述:maven项目是模块化的,各个项目之间可以互相依赖。如果一个项目依赖于另一个项目,那么被依赖的项目必须在仓库中;maven的依赖具有传递性,但是我们也可以进行设置排除依赖传递;

maven项目默认的jdk版本为1.5,如果该项目jdk和本地jdk版本不一致,可能导致tomcat无法导入该项目,修改maven jdk的方法:setting.xml文件182行添加如下代码

<profiles>           <profile>                  <id>jdk-1.6</id>                  <activation>                      <activeByDefault>true</activeByDefault>                      <jdk>1.6</jdk>                  </activation>                  <properties>                      <maven.compiler.source>1.6</maven.compiler.source>                      <maven.compiler.target>1.6</maven.compiler.target>                      <maven.compiler.compilerVersion>1.6</maven.compiler.compilerVersion>                  </properties>          </profile>      </profiles>

或者直接右键项目JRE System Library–>properties方式修改jre版本也可以(局部修改);

五、依赖冲突

当 a 项目和 b 项目依赖了不同版本的相同构件(比如X构件),那么当 c 项目依赖于 a 项目和 b 项目的时候,它究竟使用了哪个项目中的构件(X构件)?

maven针对这种情况有两个原则:
1、短路优先原则:
比如 X 为某个 jar 包构件,各项目依赖于下:
A–>B–>C–>X(2.0版本):A依赖B, B依赖C, C依赖X
A–>D–>X(2.1版本):A依赖D, D依赖X
最终A项目选择地X为2.1版本(短路优先);
再比如南哥和bi哥分别依赖于不同的X构件,当山鸡依赖于南哥时,他会优选选择南哥的X构件;
2、先声明先优先原则:
比如A–>B(A依赖于B),A–>C(A依赖于C),假设A同时依赖B和C,那么B和C的依赖谁先声明就引用谁的JAR包;
即:如果路径长度相同,则谁先声明,先选择谁;

六、maven的聚合与继承

1、聚合

就是把多个模块或项目聚合到一起,比如bi哥、南哥、山鸡这三个项目,我们可以把他们聚合到一个新的mavne项目中,以便于管理(比如在该聚合项目中执行install,将会把其他子模块项目全部安装到仓库中)。
在聚合项目pom.xml中进行如下配置:

<project>      <modelVersion>4.0.0</modelVersion>      <groupId>com.juvenxu.mvnbook.account</groupId>      <artifactId>account-aggregator</artifactId>      <version>1.0.0-SNAPSHOT</version>      <packaging> pom </packaging>      <name>Account Aggregator</name>       <modules>          <module>../hongxing-bige</module>          <module>../hongxing-nange</module>         <module>../hongxing-shanji</module>       </modules>  </project> 

其中:
packaging的类型为pom ,module的值是一个以当前聚合项目的pom.xml为主目录的相对路径的项目名。

2、继承

当a项目、b项目、c项目都使用了某一个构件时,如果在这三个项目中都进行依赖配置的话,代码会比较重复。此时我们可以创建一个父maven项目,在父maven项目中引入子项目共同需要的构件,然后在子项目中继承父项目,这样子项目将不用声明依赖部分构件(从父maven项目中继承了)。

方法:
父maven项目进行pom配置如下:

<project>      <modelVersion>4.0.0</modelVersion>      <groupId>com.juvenxu.mvnbook.account</groupId>      <artifactId> account-parent </artifactId>      <version>1.0.0-SNAPSHOT</version>      <packaging>pom</packaging>      <name>Account Parent</name>  </project>  

在子项目中进行如下配置:

<project>      <modelVersion>4.0.0</modelVersion>      < parent >          <groupId>com.juvenxu.mvnbook.account</groupId>          <artifactId> account-parent </artifactId>          <version>1.0.0-SNAPSHOT</version>          < relativePath >../account-parent/pom.xml</ relativePath>      </ parent >      <artifactId> account-email </artifactId>      <name>Account Email</name>    ...  </project> >  

注意:
a、子模块没有声明groupId和version, 这两个属性继承至父模块。但如果子模块有不同与父模块的 groupId、version ,也可指定;
b、不应该继承artifactId,如果groupId ,version,artifactId 完全继承的话会造成坐标冲突;另外即使使用不同的 groupId或version,同样的 artifactId也容易产生混淆。
c、使用继承后 parent也必须像自模块一样加入到聚合模块中。
d、maven可继承的pom元素:

groupId :项目组 ID ,项目坐标的核心元素;  version :项目版本,项目坐标的核心元素;  description :项目的描述信息;  organization :项目的组织信息;  inceptionYear :项目的创始年份;  url :项目的 url 地址  develoers :项目的开发者信息;  contributors :项目的贡献者信息;  distributionManagerment :项目的部署信息;  issueManagement :缺陷跟踪系统信息;  ciManagement :项目的持续继承信息;  scm :项目的版本控制信息;  mailingListserv :项目的邮件列表信息;  properties :自定义的 Maven 属性;  dependencies :项目的依赖配置;  dependencyManagement :醒目的依赖管理配置;  repositories :项目的仓库配置;  build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;  reporting :包括项目的报告输出目录配置、报告插件配置等。  

e、dependencyManagement的特性:在dependencyManagement中配置的元素既不会给parent引入依赖,也不会给它的子模块引入依赖,仅仅是它的配置是可继承的。因此我们可以利用这个标签将子模块需要的依赖配置配置在父模块中,然后子模块利用 parent 继承父模块;

聚合与继承的共同点:
a、聚合 POM与继承关系中的父POM的 packaging都是pom
b、聚合模块与继承关系中的父模块除了 POM之外都没有实际的内容。
c、在现有的实际项目中一个 POM既是聚合POM,又是父 POM,这么做主要是为了方便

1 0