一、Maven简介
1.1 何为Maven
maven是Apache一个开源项目,主要服务于基于java平台的项目构建、依赖管理和项目信息管理。
1.1.1 何为构建
除了我们在编写代码,其他诸如编译、生成文档、单元测试、打包和部署等,都是构建的工作。
1.1.2 Maven是优秀的构建工具
maven作为一个构建工具,不仅帮我们自动化构建,还能抽象构建过程,而且他跨平台,对外提供了一致的接口。
1.1.3 Maven不仅仅是构建工具
maven也是依赖管理的工具和项目信息管理工具,通过一组坐标来定位唯一的java类库(jar文件),还提供一些项目文档信息、测试报告以及源码版本日志报告等信息。此外,maven还提供一个免费开源的中央仓库,以及基于约定优于配置的原则。
1.2 为什么需要Maven
Maven不是java领域的唯一构建工具,下面将通过比较IDE、Make和Ant进行比较。
1.2.1 组装PC和品牌PC
类似于买电脑,自己组装的费时又缺乏稳定性,但购买品牌既省时又稳定,使用maven构建工程就可以做到省时省力,且具有maven社区的大量支持。
1.2.2 IDE不是万能的
IDE虽然很方便开发,但是对于构建项目而言,每一次的点击鼠标的行为是愚蠢的,又低效又易出错,而maven作为这方面的专家,又得到了很多开发工具(如:eclipse、IDEA等)的支持,因此可以极大的减少开发成本。
1.2.3 Make
make是较为早期的构建工具,现在也有很多的衍生品,效果看起来还不错,它由一个名为MakeFile的脚本文件驱动,拥有自己的语言结构。
一大优点是可以调用所有系统的本地命令,功能较为强大,但也表明了无法支持跨平台,对于java很不友好。而且基于语法的原因,出错率较高。
1.2.4 Ant
ant最早用来构建TomCat,其作者因为受不了makefile的语法才设计的ant,且其可以看做是java版本的make,使用xml格式的文件进行构建过程。
早期的ant是手工来管理依赖的,现在可借助Ivy管理依赖,相比于maven并无太大差别,但maven具有中央仓库,无需配置即可使用。
二、Maven的安装和配置
2.1 在windows上安装
2.1.1 检查JDK安装
maven支持jdk1.4以上版本,在dos终端运行命令:
echo %JAVA_HOME%
java -version
结果如下:
如果出现错误,则需要检查JDK安装是否有误。
2.1.2 下载maven
访问官网http://maven.apache.org下载相关的版本,建议3.0以上的版本。
2.1.3 本地安装
解压文件之后,在系统环境变量中新建一个变量,名为MAVEN_HOME,值是maven安装的目录,如下:
之后在Path变量中加入%MAVEN_HOME%\bin,如下(注:Path变量作用是为系统提供在哪些位置寻找可执行文件或脚本):
最后在dos终端运行 mvn -v 结果如下:
2.2 安装目录分析
2.2.1 MAVEN_HOME
该变量指向了maven的安装目录,其结构如下:
bin:该目录包含到了mvn运行的脚本,这些脚本用来配置java命令,准备好classpath和java的系统属性,然后执行java命令。其中还有一个m2.conf文件,该文件是配置classworlds的。
boot:该目录包含一个plexus-classworlds-2.6.0.jar文件,plexus-classworlds是一个类加载器框架,相比于java默认的类加载器,有更丰富的语法以方便配置,用于加载maven自身类库的。
conf:该目录包含一个非常重要的目录,settings.xml,是maven的配置文件,能够全局的修改maven的行为。
lib:该目录包含了maven运行时需要的java类库,其中还有一个超级pom。可以说该目录才是真正的maven本身
LICENSE:记录了maven使用的软件许可证。
NOTICE:记录了maven包含的第三方软件。
README:包含了maven的简要介绍。
2.2.2 ~/.m2
首先我们运行一个命令 mvn help:system,该命令是一个真正的maven任务,他会打印所有java的系统属性和环境变量。另外还会下载maven-help-plugin插件,包括pom文件和jar文件。
在用户目录下会有一个.m2目录,该目录包含一个resposity目录,是maven的本地仓库。根据项目的需要我们可以更换我们的本地仓库所在的位置。
2.3 与开发软件集成
以IDEA为例,基本每个开发软件都会有一个内置的maven,但建议不要使用,默认换成自己下载的版本,因为可能存在不稳定等因素。需要修改配置,修改maven的版本,本地仓库以及settings.xml文件等。
三、坐标和依赖
maven为了能自动化的解析任何一个java构件,皆因坐标这个唯一标识,下面就会进行详细介绍。
3.1 何为maven坐标
在开发的时候,当我们需要不同的依赖java库时,不需要再各个网站上去下载,通过在pom.xml文件中描述坐标告知maven,让他去中央仓库(http://repo1.maven.org)去下载,中央仓库包含了世界上大部分开源的java构件。
3.2 坐标详解
maven的坐标为各个java构件提供了统一的管理标准,坐标元素包括:groupId、artifactId、version、packaging、classifier。看一组坐标定义:
下面对各个元素进行详解:
groupId:定义当前maven项目隶属的实际项目,一般是域名反向,与java包名表示很相似。
artifactId:该元素定义了一个实际项目的一个maven项目(模块),建议使用实际项目名作为前缀,在默认情况下,maven生成的构件文件会以artifactId作为文件名,比如jt-web-1.1.jar。
version:该元素定义了当前项目所处的版本。
packaging:定义项目的打包方式,默认是jar,而不同的打包方式具有不同的生命周期。
classifier:帮助定义的构件输出一些附属构件,不能直接定义的。
另外,值得一提的是,maven项目生成的构件名一般遵循以下规则,artifactId-version [-classifier].packaging,其中classifier是可选的。
3.3 依赖配置
基本依赖配置如下:
在根元素project下的dependencies下可以有一个或多个dependency元素,代表一个或多个依赖。每一个依赖元素可以包含以下元素:
groupId、artifactId、version:定义了一个坐标。
type:依赖的类型,默认下是jar,可以不声明。
scope:依赖的范围。
optional:标记依赖是否可选。
exclusions:用来排除依赖性传递。
注:大部分依赖只需要坐标即可。
3.4 依赖范围
maven项目在编译、测试和运行的时候使用的是三个不同的classpath,依赖范围就是为了控制依赖与这些classpath的关系的,maven有以下范围:
complie:编译依赖范围,默认三个过程都有效,也是maven的默认依赖范围,如:spring-core。
test:测试依赖范围,在编译和运行时无法使用该范围的依赖,如:JUnit。
provided:在编译和测试有效,在运行时无效,典型的例子就是servlet-api,在运行时容器会提供,无需maven重复引入一遍。
runtime:对测试和运行时有效,例如JDBC接口,只有在运行的时候才需要实现JDBC接口的具体驱动。
system:这是和provided一致的范围,但是这不是与maven仓库绑定的,而是与操作系统绑定的,因此可能会有移植性的问题。慎用!!
import:不会对三种classpath产生实际影响。
3.5 传递性依赖
3.5.1 何为传递性依赖
在进行项目依赖的时候,比如spring-core会依赖其他第三方的项目,为了方便依赖,无需我们去干预,maven提供了依赖传递规则,按照最短路径作为第一原则,声明顺序作为第二原则的依赖传递帮助我们解决了上述问题。
3.5.2 传递性依赖和传递范围
假设三个项目,A依赖于B,B依赖于C,则A对B是第一直接依赖,B对C是第二直接依赖,A对C是传递性依赖。在下图中方便理解,最左一列是第一直接依赖,最上面一行是第二直接依赖,交叉的部分是传递性依赖:
compile | test | provided | runtime | |
---|---|---|---|---|
compile | compile | —— | —— | runtime |
test | test | —— | —— | test |
provided | provided | —— | provided | provided |
runtime | runtime | —— | —— | runtime |
3.5.3 可选依赖
假设有如下情况,项目A依赖于B,而B项目有两个特性,分别依赖两个互斥的项目来构建的,如:数据库依赖,B在构建的时候需要两者依赖(且是可选依赖),但在运行的时候只需要其中一个,因此用到了可选依赖,而可选依赖对A并没有影响。
B项目的依赖中对于两种可选依赖使用optional(值为true)元素描述,在A中根据实际需要哪个依赖进行显示声明即可。
注:一般不建议使用可选依赖。
3.5.4 排除依赖
在开发的时候有如下情况,当前项目依赖一个第三方项目,而这个第三方项目依赖了一个目前处于开发阶段的其他依赖,此时这个不稳定版本需要排除在当前项目外,因此可以使用exclusion元素排除,如下:
3.5.5 归类依赖
比如springframework项目下有很多模块,这些模块同属于一个项目,因此当升级的时候需要逐一修改版本,为了避免这个重复的操作,可以使用properties元素定义一个maven属性,值为依赖的版本,此时可以在依赖的version中使用${元素名}的方式引用该值。如:
而各个模块可以引用这个属性:
四、仓库
4.1 何为maven仓库
每个maven项目所需要的的依赖虽然不相同,但难免存在重复依赖,为了能够避免在磁盘中存储重复的项目,仓库就发挥了作用,在所有的maven项目都会使用同一个仓库,而且仓库中没有重复的项目,当哪个项目需要一些依赖时,通过pom.xml文件描述即可。
4.2 仓库的布局
在maven的仓库中,所有的项目基本都遵循如下存储路径:groupId / artifactId / version / artifactId-version.packaging,其中各个位置的信息都在各个项目的pom.xml文件中描述了。
4.3 仓库的分类
maven的仓库大概分为两大类,本地仓库和远程仓库。远程仓库有三种,分别是maven默认的中央仓库、企业使用的私服和其他远程仓库(如:阿里等):
4.3.1 本地仓库
默认情况下,maven项目在进行依赖导入的时候,首先去本地仓库下查找,而本地仓库在C盘的用户目录下一个名为.m2的目录中,下面有repository目录,此目录就是本地仓库。
如果想要改变本地仓库的位置,需要修改settings.xml文件(建议复制一份文件,最好不要直接使用maven的全局settings.xml文件),修改如下:
如果在项目中需要用到我们自己的其他项目,本地仓库和远程仓库是没有的,此时可以使用maven的插件帮助我们生成自己的jar或war文件,并加入到本地仓库中,使用的是mvn install的命令,他会帮我们生成自己的jar或war文件,并根据pom.xml文件的描述放在本地仓库对应的坐标的位置。
4.3.2 远程仓库
远程仓库相对于本地仓库而言,可以配置多个,当我们的项目依赖无法在本地仓库中找到时,就会去这些远程仓库中下载并放到本地仓库中。
4.3.3 中央仓库
中央仓库是maven默认的远程仓库,可以在maven安装目录下的lib下找到maven-model-builder-3.6.jar(版本可能不同),解压后可以看到如下配置文件,org/apache/maven/model/pom-4.0.0.xml,这是所有maven都会继承的超级pom(后续会介绍),其中有一部分如下配置:
这就为maven配置了默认的远程仓库,即中央仓库。
4.3.4 私服
私服是架设在局域网的仓库,构建图如下:
作用如下:
节省自己的外网带宽,可以消除重复的构件下载。
加速maven构建,访问内网与外网的差异。
部署第三方构件,有些远程仓库没有的构件可以放到私服上,供大家使用。
提高稳定性,增强控制,在没有Internet情况下也可以构建项目,另外成熟的私服软件(如:Nexus),还提供很多如权限管理等功能。
降低中央仓库的负荷,可以减少外网的访问。
4.4 远程仓库的配置
当中央仓库无法满足我们的项目时,我们可以配置其他的远程仓库,在项目的pom.xml中填写如下配置:
<project>
...
<repositores>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repostory.jboss.com/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<layout>default</layout>
</repository>
</repositores>
</project>
在上述配置中,respositores元素可以配置一个或多个远程仓库,注:仓库的id必须唯一,且不可使用maven默认中央仓库的central,否则就会覆盖掉中央仓库。
除了id、url、name等元素外,releases和snapshots元素控制着项目的发布版本和快照版本的下载,他们的enabled元素代表是否支持下载。layout元素(值为default)表示使用默认的maven2和maven3的布局。
对于releases和snapshots元素而言,除了enabled子元素外,还有如下子元素:
<snapshots>
<enabled>true</enabled>
<!--表示从远程仓库检查更新的频数
取值:daily(每天)、never(从不)、always(每次构建都会检查)、interval:X(每隔X分钟检查一次)
-->
<updatePolicy>daily</updatePolicy>
<!--
用来配置检查检验和文件的策略,当下载构件时,如果出错会根据配置的值采取不同的措施
值:warn:构件时输出警告信息、fail:遇到错误就停止构建、ignore:忽略检验
-->
<checksumPolicy>ignore</checksumPolicy>
</snapshots>
4.4.1 远程仓库的认证
对于大部分远程仓库而言,都可直接访问,但有的个人或公司的maven仓库需要进行认证,以保证安全,所以需要在项目的settings.xml中配置认证信息。注:pom文件在进行访问仓库的时候需要将pom提交到被访问的仓库,为了安全,选择了只放在本机的settings.xml文件中配置。
<settings>
...
<servers>
<server>
<!--id元素绑定了要访问的仓库以及用户密码的认证信息-->
<id>myProjetc</id>
<username>root</username>
<password>root</password>
</server>
</servers>
...
</settings>
4.4.2 部署至远程仓库
maven除了可以帮我们编译、测试、打包项目,也可以将项目部署到仓库中供其他团队使用,如下配置pom.xml文件即可:
<project>
<distributionManagement>
<respository>
<id>发布版本仓库id</id>
<name>方便阅读的名字</name>
<url>仓库地址</url>
</repository>
<snapshotRespository>
<id>快照版本仓库id</id>
<name>方便阅读的名字</name>
<url>仓库地址</url>
</snapshotRespository>
</distributionManagement>
</project>
上述配置完成后,通过命令mvn clean deploy即可完成远程部署,注:部署时需要认证信息,配置方式也是在settings.xml中加入server元素。
4.4.3 快照版本
假设这样一个情况,两个人分别同时开发项目A和B,而B依赖于A,因此,B的构建需要时不时的去拿到A的最新版本,这样为了坐标不冲突(因为坐标一样就不会去下载到本地使用),需要不断的修改版本信息。而快照机制是在每个项目发布快照版本后会生成时间戳来标识不同的快照版本,而maven也能据此拿到最新的版本以供开发,正因为如此,所以快照版本是不稳定的版本,仅仅用于公司内部开发测试使用。
4.5 镜像
镜像意为真实仓库的一个复制版,如http://maven.net.cn/content/groups/public是中央仓库http://repo1.maven.org/maven2的一个在国内的镜像,用来提供更快速的服务,可以在settings.xml中配置maven的镜像:
<settings>
...
<mirrors>
<mirror>
<id>仓库id</id>
<name>仓库名</name>
<url>仓库地址</url>
<!--配置的哪个仓库的镜像,本例中是中央仓库,因此任何访问中央仓库的请求都会被改为请求该镜像-->
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
...
</settings>
关于镜像的另一个用法是结合私服,可以在私服配置所有外部远程仓库的镜像,如下:
<settings>
...
<mirrors>
<mirror>
<id>私服仓库id</id>
<name>私服仓库名</name>
<url>私服仓库地址</url>
<!--其中mirrorOf的值可以为:
*:匹配所有远程仓库
external:*:匹配所有非本机的仓库
repo1,repo2:匹配repo1和repo2这两个仓库
*,!repo1:匹配所有除了repo1的远程仓库
-->
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
</settings>
4.6 仓库搜索服务
开发中需要根据关键字来查询仓库,目前提供了几个仓库搜索服务的软件,如下:
1:Sonatype Nexus(地址:http://repository.sonatype.org)
2:Jarvana(地址:http://www.jarvana.com/jarvana)
3:MVNbrowser(地址:http://www.mvnbrowser.com)
4:MVNrepository(地址:http://mvnrepository.com)
五、生命周期和插件
5.1 何为生命周期
为了统一项目的构建过程而抽象出来的概念,如清理、初始化、编译、测试、打包、发布等过程,而生命周期是抽象出来的概念,真正执行的是maven的插件。
5.2 生命周期的详解
5.2.1 三套生命周期
maven提供了三套相互独立的生命周期,clean(目的是清理项目)、default(目的是构建项目)、site(目的是构建项目站点)。每个生命周期都有顺序的几个阶段。
5.2.2 clean生命周期
clean作用是清理项目,其三个阶段:
pre-clean:执行清理前的工作。
clean:清理上一次构建生成的文件。
post-clean:执行清理后的工作。
5.2.3 default生命周期
default是最核心的生命周期,在构建项目的主要步骤都在此生命周期中,下面列举了该周期的阶段(仅对重要的阶段进行了解释):
validate
initialize
generate-sources
process-sources:处理项目主资源文件,一般是src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录。
generate-resources
process-resources
compile:编译项目的主源码,一般是编译src/main/java下的源码文件至项目输出的主classpath目录。
process-classes
generate-test-sources
process-test-sources:处理项目的测试资源文件,一般是将src/test/resources下的内容进行变量替换后,复制到项目输出的测试classpath中。
generate-test-resources
process-test-resources
test-compile:编译测试代码,一般是将src/test/java下的文件编译至项目输出的测试classpath中。
process-test-classes
test:使用单元测试框架运行测试,测试代码不会被打包或部署。
prepare-package
package:接收编译好的代码,打包为发布格式。
pre-integration-test
integration-test
post-integration-test
verify
install:将包安装到本地仓库。
deploy:将最终的包复制到远程仓库。
5.2.4 site生命周期
maven根据pom的信息生成一个友好的站点,这都归功于site,他包括如下阶段:
pre-site:生成站点之前的工作。
site:生成项目站点文档。
post-site:生成站点之后的工作。
site-deploy:将生成的站点发布到服务器上。
5.2.5 命令行与生命周期
从命令行调用mvn的生命周期时,各个周期互相独立,而周期内是具有前后依赖关系的,如下几个常用的命令:
mvn clean:实际执行的是clean的pre-clean和clean。
mvn test:实际执行的是default周期的validate到test中的所有阶段。
mvn clean install:调用了clean的pre-clean和clean,以及default的validate到install的所有阶段。
5.3 插件目标
插件目标就是每一个功能,一个插件可以有多个功能(即目标)
5.4 插件绑定
插件绑定就是把每个周期和其对应的插件的目标进行绑定。
5.4.1 内置绑定
为了更快的构建项目,maven内置了一些绑定,如下:
clean的生命周期:
生命周期阶段 | 插件目标 |
---|---|
pre-clean | |
clean | maven-clean-plugin:clean |
post-clean |
site的生命周期:
生命周期阶段 | 插件目标 |
---|---|
pre-site | |
site | maven-site-plugin:site |
post-site | |
site-deploy | maven-site-plugin:deploy |
对于default生命周期,他的绑定关系由打包类型决定,因为不同的打包方式会有不同的构建过程。
5.4.2 自定义绑定
在内置绑定之外,我们还可以进行自定义的绑定,因此maven在构建过程中可以执行丰富的任务,举一个常见的例子,创建项目的源码jar包:maven内置的没有这个功能,需要maven-source-plugin插件的jar-on-fork目标帮助我们完成,配置如下:
<project>
...
<build>
<!--build元素下的plugins的plugin元素声明插件的使用-->
<plugins>
<plugin>
<!--插件的坐标-->
<groupId>org.apahce.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<!--executions下的execution用来配置执行一个任务-->
<executions>
<execution>
<!--任务的id-->
<id>attach-sources</id>
<!--任务生效的生命周期阶段,注:不指定默认会绑定在插件默认提供的阶段,每个插件不一样-->
<phase>vertify</phase>
<!--配置指定要执行的插件目标-->
<goals>
<goal>jar-on-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
5.5 插件的配置
5.5.1 命令行插件配置
mvn install -D key = value的形式,-D是java自带的,作用是通过命令行设置一个java系统属性,maven重用了该参数,其中key=value是每个插件提供的参数选项而定。
5.5.2 pom中插件全局配置
对于一些不常改变的参数,不适合在命令行中配置,需要在pom中配置一次即可,例如:配置插件maven-compiler-plugin告诉他编译java1.5的源码,并生成与jvm1.5兼容的class文件:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
5.6 获取插件信息
5.6.1 在线插件信息
目前有两大网站提供较多的插件信息,如apache的官网,除了apache外,托管于Codehaus上的Mojo项目(官网)也提供了大量的插件.
5.6.2 使用maven-help-plugin描述插件
可以通过该插件来得到相应插件的信息,命令如下:mvn help :describe-Dplugin=org.apache.maven.plugins:maven-compiler-plugin:2.1来得到信息。
5.7 插件解析机制
5.7.1 插件仓库
与依赖的仓库类似,在maven查找插件的时候也是先在本地仓库查找,没有的话去默认的远程仓库(中央仓库)查找,我们可以在pom或settings.xml文件中配置其他的远程插件仓库。
5.7.2 插件的默认groupId
在maven中,插件默认的groupId是org.apahce.maven.plugins,默认可以不写,但不推荐这么做。
5.7.3 默认的插件版本
在maven中,有一个超级pom,所有maven项目都继承自这个pom,其中定义了核心插件的默认版本,如果在自己的项目pom中没有显示的声明version,会使用超级pom定义的版本,如果不是核心插件,默认去所有仓库查找可用的最新版本,因为有可能是快照版本,所以建议显示的声明所用插件的版本。
六、聚合与继承
6.1 聚合
有的时候,我们希望能一次构建一个项目的多个模块,甚至所有模块,这就需要借助聚合来实现了,看一个例子:
<project>
<modelVersion>1.0.0</modelVersion>
<groupId>com.tg.web</groupId>
<artifactId>tg-web</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!--packaging值是pom代表当前项目是一个聚合项目-->
<packaging>pom</packaging>
<name>TG</name>
<!--这个元素表示一系列要聚合的模块-->
<modules>
<!--每个module代表一个模块,值就是当前聚合模块的相对目录值,也可以是和聚合工程模块平级,也可以是在聚合模块的目录下-->
<module>tg-sso</module>
<module>tg-manage</module>
</modules>
...
</project>
这样,maven会首先解析聚合模块的pom,分析要构建的模块,并计算出一个反应堆(后续解释)构建顺序。
6.2 继承
在java的面向对象中,可以使用父子类去除重复,在maven中也可以通过父工程和子工程来实现去除重复,下面以一个父工程和子工程的pom为例讲解。
6.2.1 父工程
如下是父工程的pom:
<project>
<modelVersion>1.0.0</modelVersion>
<groupId>com.jt</groupId>
<artifactId>jt-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!--作为父模块,其打包方式也必须是pom-->
<packaging>pom</packaging>
<name>JtParent</name>
</project>
因为父工程只是为了消除配置的重复,因此不需要src/main/java等内容,仅仅一个pom足以。
6.2.2 子工程
如下是一个子工程:
<project>
<modelVersion>1.0.0</modelVersion>
<!--定义了一个父元素,其中前三个子元素是坐标,必须写,最后一个是查找父工程的pom,找不到会报错,默认去上一级目录下找-->
<parent>
<groupId>com.jt</groupId>
<artifactId>jt-parent<artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../jt-parent/pom.xml</relativePath>
</parent>
<!--因为当前pom继承了父工程的pom,所以groupId及version等不需要声明-->
<artifactId>jt-web<artifactId>
<name>JtWeb</name>
<dependencies>
...
</dependencies>
<build>
<plugins>
...
<plugins>
</build>
</project>
此外还需要将父工程放在聚合工程的modules元素中,以便一同构建。
6.2.3 可继承的pom元素
如下列表是可继承的元素:
- groupId:项目组id
- version:项目版本
- description:项目的描述信息
- organization:项目的组织信息
- inceptionYear:项目的创始年份
- url:项目的url地址
- developers:项目的开发者信息
- contributors:项目的贡献者信息
- distributionManagement:项目的部署配置
- issueManagement:项目的缺陷系统跟踪信息
- ciManagement:项目的持续继承系统信息
- scm:项目的版本控制系统信息
- mailingLists:项目的邮件列表信息
- properties:自定义的maven属性
- dependencies:项目的依赖配置
- dependencyManagement:项目的依赖管理配置
- repositories:项目的仓库配置
- build:项目的源码目录、输出目录、插件目录及插件管理配置等
- reporting:项目的报告输出目录配置、报告插件配置
注:为了方便,可以将聚合模块和父工程模块合并为一个模块。
6.3 约定优于配置
前面说过,所有maven项目都继承一个超级pom,下面看一下这个pom中的一部分内容:
<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>
可以看到,这个pom配置了中央仓库的位置,插件仓库的位置,源码目录等信息,这个超级pom为我们做了一些默认的配置,我们应当遵循这个约定,如果想自定义实现,就会失去了通用性,且配置较为复杂,因此maven是一个约定优于配置的工具,我们应该遵循。
6.4 反应堆
反应堆是所有模块组成的一个构建结构,这个结构是一个有向非循环图,当解析当前pom时,如果有其他依赖会查找并解析,以此类推,知道尽头,最后构成一个反应堆,因为非循环,所以如果A依赖B,而B依赖A则会构建失败。
总结
根据上述对maven的讲解,相信读者对maven工具有了大致的了解,虽然不全,但是对于大多数情况下的开发而言足以。下面就可以进行我们的开发之旅了!!