pom.xml:maven项目的核心,定义了项目的基本信息,用于描述项目如何构建,声明项目的依赖,等等。
下面一步步解析pom.xml文件的相关配置。
如图:
project:是pom.xml的根元素,声明了POM相关的命名空间及xsd元素。
modelVersion:指定了当前POM的模型版本,对于maven2和maven3来说它只能是4.0.0。
groupId:定义了项目属于哪个组,这个组往往和项目所在的组织或公司相关联。例如图中定义理解为:vinuxpay的mvntest项目。
artifactId:定义了当前maven项目在组中的唯一ID,用来与其他不同的项目或者模块区别开来。例如图中是为HelloWorld项目定义一个artifactId为hello-world。默认情况下会以artifactId值开头生成文件。
version:定义当前项目的版本。SNAPSHOT说明当前项目处于开发中,为不稳定版本,随着项目的升级,version会不断的更新。
packaging:定义maven项目的打包方式,如果不定义,默认为jar包。
name:项目名称,不是必须的,但是还是推荐为每个POM申明,以方便信息交流。
description:对项目的描述,不是必须的。
最重要的groupId、artifactId、version三个元素定义了maven项目的基本坐标,任何的jar、pom或者war都是基于这些接本的坐标进行区分的。
依赖
依赖配置
如图:
project > dependencies元素用来配置项目依赖,一个dependencies下可以配置多个dependency元素用来申明一个或多个项目依赖。
groupId、artifactId、version依赖的基本坐标,对于任何一个依赖来说坐标是最重要的,Maven根据坐标来查找依赖。
type:依赖类型,对应于项目坐标定义的packaging。大部分情况下该属性不必声明,默认为jar。
scope:依赖范围。用来控制依赖与编译、测试、运行三种classpath的关系。Maven有以下依赖范围:
compile:编译依赖范围。如果没有指定,就默认使用该范围,对于编译、测试、运行三种classpath都有效。典型的例子是spring-core,在编译、测试、运行时都要使用该依赖。
test:测试以来范围,只对测试时有效。例如Junit,只有在编译和运行测试的时候有效才需要。
provided:已提供依赖范围。只对编译和测试的classpath有效,运行时无效。例如servlet-API,因为容器已提供,就不需要Maven再引入。
runtime:运行时依赖范围。在测试和运行的classpath有效,编译时无效。例如JDBC驱动实现,项目主代码编译只要提供JDK的JDBC接口,只有在测试和运行时才需要实现上述接口的JDBC驱动。
system:系统依赖范围。依赖关系和provided依赖关系一致。使用时必须通过systemPath显示的指定以来文件路径。由于此依赖不是通过Maven仓库解析,而是与本机系统绑定,会造成项目移植不可用,需谨慎使用。
systemPath也可引用环境变量,如:<systemPath>${JAVA_HOME}/lib/rt.jar</systemPath>
import(Maven2.0.9以上) : 导入依赖范围。
optional:可选依赖。用来标记依赖是否可选(true/false)。
exclusions:声明排除传递性依赖。
传递性依赖
最基本理解就是:假设项目A对项目B有一个compile范围依赖,而项目B对项目C也有一个compile范围依赖,那么,C就会成为A的一个compile范围依赖。C就是A的一个传递性依赖。好处就是:一方面是简化和方便了依赖申明,另一方面只需关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入什么传递性依赖。
可选依赖(optional)
假设项目A依赖于项目B,项目B依赖于项目X和Y,但是B对于项目X和Y都是可选依赖。如果三者的依赖范围都是compile,那么X.Y对于A就是传递性依赖,但是由于X、Y是可选的,那么对于A来说一来就不会传递。例如多数据库工具包,在构建这个工具包的时候,需要多种数据库驱动;但是在使用的时候只会依赖一种。
上图表示使用optional元素表示mysql-connector-java和postgresql这两个依赖为可选依赖,他们只会对B产生影响。当A依赖B项目的时候,这两个依赖不会被传递。当A依赖B的时候,如果使用基于MySQL的数据库,就需要在A中声明mysql-connector-java这一依赖。
最后要说明一点:在理想状态下是不应该使用可选依赖的,使用可选依赖的原因就是某一个项目实现了多个特性。基于面向对象的单一性原则,一个类只应该有一项功能,更好的做法是为mysql-connector-java和postgresql分别创建一个maven项目,基于同样的groupId分配不同的artifactId,根据需要选择。
排除依赖(exclusions)
假设项目A依赖项目B,项目B依赖项目C,但是项目C是SNAPSHOT不稳定版本。由于传递性依赖,会照成项目A不稳定,因此需要在依赖B时排除对项目C SNAPSHOT 版本的依赖,并且在项目A中声明项目C的正式发布版本。
如图,代码中使用了executions声明排除依赖,可以包含一个或者多个execution子元素,因此可以排除一个或多个传递性依赖。但要注意的是:声明execution只需要groupId和artifactId,而不需要version元素。这是因为只要groupId和artifactId就能唯一定位依赖中的某个依赖。换句话说,Maven解析后的依赖中,不可能出现两个groupId和artifactId都相同,而version不同的两个依赖。
归类依赖
有点类似于定义java常量的意思,在一处定义了直接调用就行,而不需要重复定义,或者修改常量值得时候,只需修改一处而不是逐个修改,避免了因为遗漏带来的不必要麻烦。
如图,首先使用properties元素定义Maven属性,然后定义子元素springframework,值为2.5.6。maven在运行的时候会将POM中的所有${springframework.version}替换成实际值2.5.6。
----------------------------------------------------------------------------------------------------------------
Maven会自动解析所有项目的直接依赖和传递性依赖,并且根据规则正确判断每个依赖的范围,对于一些依赖冲突也能进行调节,确保任何一个构建只有唯一的版本在依赖中存在。
-----------------------------------------------------------------------------------------------------------------
仓库
Maven用某一位置存储所有Maven项目共享构建,这位置就叫仓库。任何构建都有groupId、artifactId、version这一坐标,根据坐标可以确定其在仓库存储的唯一路径。
路径与坐标的关系大致是:groupId/artifactId/version/artifactId-version.packaging。例如上图的MVN测试hello-world依赖,在仓库的路径就是:vinuxpay.mvntest/vinuxpay.mvntest.hello-world/0.0.1-SNAPSHOT/vinuxpay.mvntest.hello-world-0.0.1-SNAPSHOT.jar。
分类
分为两类:本地仓库和远程仓库。远程仓库又包括:中央仓库(Maven核心自带)、私服、其他类型仓库。如图:
构建查找顺序: 先查找本地仓库,如果本地仓库存在此构建,直接使用。如果不存在,就去远程仓库查找,并且下载到本地。如果本地和远程都没有,Maven就会报错。
本地仓库
默认路径: ${user.home}/.m2/repository。
自定义路径:修改MAVEN_HOME/config/setting.xml文件的localRepository元素值,如图:
对于本地仓库的依赖,一种是从远程仓库中下载至本地仓库,另一种是将本地项目的构建通过在该项目路径下执行mvn clear install安装。
远程仓库
默认:Maven自带的核心--中央仓库。
配置:在repositories元素下使用repository配置一个或者多个远程仓库。
id:仓库名称,必须唯一。不能声明和Maven自带中央仓库的id一样(central),否则就会覆盖掉中央仓库。
url:仓库地址,基于http协议。
releases和snapshots:用来控制Maven对发布版和SNAPSHOTS版本构建的下载。如果enabled元素值为true,表示开启发布版本的下载支持,但不支持SNAPSHOTS版本的下载支持。
updatePolicy:表示远Maven对程仓库检查更新的频率。默认daily,表示每天检查一次;never:从不检查更新;always:每次构建都检查;interval:X--每隔X分钟检查一次更新。
checksumPolicy:用来配置Maven检查检验和文件的策略。当构建被部署到仓库时,会同时部署对应的校验和文件。默认为warn:Maven会在构建时输出警告信息;fail:Maven会在遇到校验和错误就会让构建失败;ignore:完全忽略校验和错误。
远程仓库部署(mvn clean deploy)
将项目构建部署到远程仓库(一般是自建的私服)中POM配置如下:
repository:发布版本构建的仓库。
snapshotRepository:SNAPSHOT版本的仓库。
id:该仓库的唯一标识。
对远程仓库进行构建部署时候,出于安全方面的考虑,有时我们要对远程仓库的访问进行认证,一般将认证信息配置在settings.xml中:
id :要与POM中repository元素id一致。
username:认证名。
password:认证密码。
镜像
如果仓库A能够提供仓库B的所有内容,那么A就是B的一个镜像。例如http://maven.net.cn/content/groups/public就是Maven中央仓库http://repol.maven.org/maven2在中国的一个镜像。由于地理位置因素,该镜像往往能够比中央仓库提供更快的服务。因此,可以配置该镜像来代替中央仓库。配置setting.xml如下:
中央仓库镜像配置
配置私服镜像
<mirrorOf>的相关配置:
<mirrorOf>*</mirrorOf>:配置所有远程仓库
<mirrorOf>external:*</mirrorOf>:匹配所有不在本机上的远程仓库
<mirrorOf>repo1,repo2</mirrorOf>:匹配仓库repo1和repo2,多个仓库之间用逗号分隔。
<mirrorOf>*,!repo1</mirrorOf>:匹配除repo1以外的所有远程仓库。感叹号表示排除
****************************************************未完,后续更新****************************************