一 关于pom.xml 的文件的详解
1 定义
pom:Project Object Model,项目对象模型。通过xml格式保存的pom.xml文件。作用类似ant的build.xml文件,功能更强大。该文件用于管理:源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目授权、项目的url、项目的依赖关系等等。
2 关于官方的完整的pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<modelVersion>4.0.0</modelVersion>
<!– The Basics –>
<groupId>…</groupId>
<artifactId>…</artifactId>
<version>…</version>
<packaging>…</packaging>
<dependencies>…</dependencies>
<parent>…</parent>
<dependencyManagement>…</dependencyManagement>
<modules>…</modules>
<properties>…</properties>
<!– Build Settings –>
<build>…</build>
<reporting>…</reporting>
<!– More Project Information –>
<name>…</name>
<description>…</description>
<url>…</url>
<inceptionYear>…</inceptionYear>
<licenses>…</licenses>
<organization>…</organization>
<developers>…</developers>
<contributors>…</contributors>
<!– Environment Settings –>
<issueManagement>…</issueManagement>
<ciManagement>…</ciManagement>
<mailingLists>…</mailingLists>
<scm>…</scm>
<prerequisites>…</prerequisites>
<repositories>…</repositories>
<pluginRepositories>…</pluginRepositories>
<distributionManagement>…</distributionManagement>
<profiles>…</profiles>
</project>
3关于pom的一些标签的定义
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>反写公司网址+项目名</groupId>
<artifactId>项目名+模块名</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--
version中书写项目的版本号
第一个0表示大版本号
第二个0表示分支版本号
第三个1表示小版本号
snapshot快照版本
alpha内测版
beta公测版
Release稳定版
stable稳定版
GA正式发布
-->
<packaging></packaging>
<!--
packaging打包方式
默认是jar
还有war,pom,zip,jar等方式
-->
<name>项目的描述名</name>
<url>项目地址</url>
<description>项目描述</description>
<developers>
<developer>开发者<developer>
</developers>
<licenses>项目证书</licenses>
<orgranization>项目所属组织</orgranization>
<dependecies>
<dependency>
<groupId></groupId>
<artifactId></groupId>
<version></version>
<type></type>
<scope>依赖传递范围</scope>
<optional></optional>
<!--
设置依赖是否可选,默认是false,子项目是继承的
设置为true时,子项目不可以继承,子项目必须显示引入该依赖
-->
<exclusions>
<exclusion>
<exclusion>
<exclusions>
<!--
排除依赖,举例说明,A依赖B,B依赖C C对于A来说属于传递依赖
如果A不想依赖C,就可以使用该标签
-->
</dependency>
<dependencyManagement>依赖管理标签</dependencyManagement>
<pluginManagement>插件管理<pluginManagement>
<build>
<plugins>
<plugin><plugin>
</plugins>
</build>
<parent></parent><!--用于子模块或者工程继承父工程-->
<modules></modules><!--父工程包含哪些子模块-->
<settings><settings><!--定义属性,常用来定义依赖版本号-->
</dependecies>
</project>
4 <dependecyManagement> 的用途
在 父工程的版本控制 有一定的优势
1.作用:
maven使用dependencyManagement元素来提供了一种管理项目的所有依赖版本号的方式。一般
我们会在顶层的父项目中(集合工程的pom文件中)看到dependencyManagement的身影。
dependencyManagement可以让所有的子项目在引用一个依赖的时候不用列出具体的版本号。
maven会沿着父子关系向上走直到找到一个拥有 dependencyManagement元素的项目,
然后他就会使用在这个dependencyManagement定义的版本号。
2.好处:
多个子项目都引用同一个依赖,那么就可以避免在所有的子项目里面都声明一个依赖的版本号。
当你想升级或者切换到另一个版本的时候,只需要在顶层的父容器里的升级版本号即可;同时
当你的子项目需要特定的版本时只需要在子项目中声明一个version即可。
3.注意:
在dependencyManagement里面只是声明依赖,不实际引入依赖,因此在子项目里需要显示的声明
所要使用到的依赖。
**使用pluginManagement管理插件(优化插件管理)
作用:
maven使用pluginManagement元素来提供一种插件管理的方式。maven中的pluginManagement不会
造成插件的实际行为,只有当子模块中真正配置了plugin元素且其中groupid,artifactid与
pluginManagement中的相匹配的时候pluginManagement中的配置才会影响实际插件的行为。
5 <build>标签的使用
build中的主要标签:Resources和Plugins。
resources:用于排除或包含某些资源文件
<resources>
<resource>
<targetPath>META-INF/plexus</targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/main/plexus</directory>
<includes>
<include>configuration.xml</include>
</includes>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
plugins:设置构建的插件
<build>
…
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.0</version>
<extensions>false</extensions>
<inherited>true</inherited>
<configuration>
<classifier>test</classifier>
</configuration>
<dependencies>…</dependencies>
<executions>…</executions>
</plugin>
6 关于继承关系和聚合关系的理解
用一个现实的例子来表示这两者的关系
继子 和 亲生儿子 在一个家庭中继子 和 亲生儿子在一起 聚合成了一个家庭 而相对于继子 并没有继承这个家族一些血缘关系 而亲生儿子继承了这个家族的血缘关系
聚合
我们在开发过程中,创建了2个以上的模块,每个模块都是一个独立的maven project,在开始的时候我们可以独立的编译和测试运行每个模块,但是随着项目的不断变大和复杂化,我们期望能够使用简单的操作来完成编译等工作,这时Maven给出了聚合的配置方式。
所谓聚合,顾名思义,就是把多个模块或项目聚合到一起,我们可以建立一个专门负责聚合工作的Maven 工程。
建立该project的时候,我们要注意以下几点:
1.聚合模块本身也做为一个Maven项目,它必须有自己的POM
2.它的打包方式必须为: pom
3.引入了新的元素:modules---module
4.版本:聚合模块的版本和被聚合模块版本一致
5.相对目录:每个module的值都是一个当前POM的相对目录
6.目录名称:为了方便的快速定位内容,模块所处的目录应当与其artifactId一致(Maven约定而不是硬性要求),总之,模块所处的目录必须和<module>模块所处的目录</module>相一致。
7.习惯约定:为了方便构建,通常将聚合模块放在项目目录层的最顶层,其它聚合模块作为子目录存在。这样当我们打开项目的时候,第一个看到的就是聚合模块的POM
8.聚合模块减少的内容:聚合模块的内容仅仅是一个pom.xml文件,它不包含src/main/Java、src/test/java等目录,因为它只是用来帮助其它模块构建的工具,本身并没有实质的内容。
9.聚合模块和子模块的目录:他们可以是父子类,也可以是平行结构,当然如果使用平行结构,那么聚合模块的POM也需要做出相应的更改。
继承
我们在项目开发的过程中,可能多个模块独立开发,但是多个模块可能依赖相同的元素,比如说每个模块都需要Junit,使用spring的时候,其核心jar也必须都被引入,在编译的时候,maven-compiler-plugin插件也要被引入。这时我们采用继承,就不用在每个子模块分别定义了。
如何配置继承:
1.说到继承肯定是一个父子结构,那么我们在父工程中来创建一个parent project
2.<packaging>:作为父模块的POM,其打包类型也必须为POM
3.结构:父模块只是为了帮助我们消除重复,所以它也不需要src/main/java、src/test/java等目录
4.新的元素:<parent> , 它是被用在子模块中的
5.<parent>元素的属性:<relativePath>: 表示父模块POM的相对路径,在构建的时候,Maven会先根据relativePath检查父POM,如果找不到,再从本地仓库查找
6.relativePath的默认值: ../pom.xml
7.子模块省略groupId和version: 使用了继承的子模块中可以不声明groupId和version, 子模块将隐式的继承父模块的这两个元素
7 依赖管理
依赖范围是用来控制依赖与3种classpath(编译classpath,测试classpath,运行classpath)的关系。maven有以下几种依赖范围:
1、compile 编译、测试、运行,A在编译时依赖B,并且在测试和运行时也依赖。
strus-core、spring-beans
打成war包或jar包。
2、provided 编译、和测试有效,A在编译和测试时需要B。
比如:servlet-api就是编译和测试有用,在运行时不用(tomcat容器已提供)。
不会打成war。
3、runtime:测试、运行有效。
比如:jdbc驱动包 ,在开发代码中针对java的jdbc接口开发,编译不用。
在运行和测试时需要通过jdbc驱动包(mysql驱动)连接数据库,需要的!!
会打成war。
4、test:只是测试有效,只在单元测试类中用。
比如:junit
不会打成war。
如何设置依赖范围呢?
比如我们要将mysql驱动的依赖设置为runtime范围,配置如下:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
将servlet依赖设置为provided
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
如果是compile就不需要设置了,因为compile是scope的默认值。
重新执行打包为war , 会发现servlet-api.jar已经不存在。
依赖传递
什么是依赖传递?
A->B(compile) 第一关系: a依赖b compile
B->C(compile) 第二关系: b依赖c compile
1、纵坐标:直接依赖
A依赖B,B是A的直接依赖。
在A的pom.xml中添加B的坐标。
2、横坐标:传递依赖
B依赖C,C是A的传递依赖。
3、中间部分:传递依赖的范围,A依赖C的范围。
依赖调节原则
项目A依赖于项目B,项目B依赖于项目C(v1), 项目A依赖于项目D,项目D依赖于项目E,项目E依赖于C(v2),
1、A--->B---->C(v1) ,
2、A------>D---->E----->C(v2)
项目A隐形依赖了两个版本的C,那到底采用哪个版本呢?
分析:
依赖调解第一原则:路径优先,很明显,第一种路径深度是3,第二种路径深度是4,所以,maven会采用C(v1)
依赖调解第二原则:声明优先,假设路径深度相等,那么声明在前的会被引用。