pom.xml与settings.xmljava
pom.xml与setting.xml,能够说是Maven中最重要的两个配置文件,决定了Maven的核心功能,虽然以前的文章零零碎碎有提到过pom.xml和settings.xml里面的内容,但都是大略带过,学习与研究地并不细致,本文的目的就是详细研究下这两个Maven重要的配置文件,从这两个配置文件能够牵出很是多的Maven话题。spring
Maven坐标express
首先谈一下为何要使用Maven坐标。apache
Maven世界拥有数量很是巨大的构件,也就是平时使用的一些jar、war等文件,在Maven为这些构件引入坐标概念以前,咱们没法使用任何一种方式来惟一标识全部这些构件。所以,若是须要使用Spring依赖,那么就去Spring官网寻找;若是须要使用log4j依赖,那么又去Apache官网寻找。又由于各个网站风格迥异,大量时间花费在了搜索和浏览网页的工做上。没有统一规范与法则,工做就没法自动化,重复性的劳动原本就应该交给机器来作。安全
Maven定义了这样一组规则:世界上任何一个构件均可以使用Maven坐标惟一标识,Maven坐标元素包括groupId、artifactId、version、packaging、classifier,如今只要咱们提供正确的元素坐标,Maven就能找到对应的构件。至于去哪里下载,Maven自己内置了一个中央仓库的地址"http://repo1.maven.org/maven2",该中央仓库包含了世界上绝大部分流行的开源项目构件,Mavne会在须要的时候去那里下载,固然也能够配置本身的中央仓库地址,去本身的中央仓库下载构件。服务器
举个例子,Spring的context:maven
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.6.RELEASE</version> </dependency
看一下下属的各个元素:学习
Maven坐标的概念大体上就是这样,理解Maven坐标,是理解Maven很重要的一步。网站
传递性依赖url
什么是传递性依赖,以Spring举一个例子。使用Spring的时候会依赖于其余开源的类库,此时有两种作法:
一、下载一个很大的.zip包,里面包含了全部Spring的jar,可是这么作每每就引入了许多没必要要的依赖
二、只下载spring相关的.zip包,不包含依赖,实际使用的时候根据出错信息,加入须要的其余依赖
显然这两种作法都很是麻烦,Maven的传递性依赖机制很好地解决了这一问题。打开spring-core-4.1.0.RELEASE的pom.xml,我截取一段关键部分:
<dependencies> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.9</version> <scope>compile</scope> <optional>true</optional> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> <scope>compile</scope> </dependency> ... </dependencies>
好比A项目依赖了spring-core,spring-core又依赖了commons-codec和commons-logging,那么commons-codec和commons-logging就是A项目的一个传递性依赖。有了传递性依赖机制,在使用spring-core的时候就不用去考虑它依赖了什么,也不用担忧引入多余的依赖,Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中去。
有了传递性依赖机制,一方面大大简化和方便了依赖声明,另外一方面在大部分状况下咱们只须要关心项目的直接依赖是什么而不用考虑这些直接依赖会引入什么传递性依赖,不过有时候传递性依赖也会有一些问题,此时咱们就须要清除地知道该传递性依赖是从哪条路径引入的,这就叫依赖调解,依赖调解主要有两点原则:
一、A->B->C->X(1.0),A->D->X(2.0),此时两条依赖路径上有两个版本的X,此时遵循路径最近者优先,所以X(2.0)将被解析使用
二、A->B->Y(1.0),A->C->Y(2.0),Y(1.0)和Y(2.0)的依赖长度是同样的,从Maven2.0.9开始,此时遵循第一声明者优先,即顺序最靠前的那个依赖优先
排除依赖
传递性依赖会给项目隐式地引入不少依赖,这极大地简化了项目依赖的管理,可是有时候这种特性也会带来问题。好比有种状况:
当前项目依赖A,A因为某些缘由依赖了另一个类库的SNAPSHOT版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,二SNAPSHOT的不稳定性将直接影响到当前的项目,此时就须要排除该SNAPSHOT,而且在当前项目中声明该类库的某个正式发布的版本
排除依赖很简单,看一下写法:
<dependency> <groupId>com.alibaba.rocketmq</groupId> <artifactId>rocketmq-client</artifactId> <version>3.2.7</version> <exclusions> <exclusion> <groupId>apache-lang</groupId> <artifactId>commons-lang</artifactId> </exclusion> </exclusions> </dependency>
这里我引入了rocketmq的依赖,可是我不想依赖rocketmq里面的apache-lang,而想要本身引入依赖,因此我就把apache-lang给排除了。
这里须要注意的是,声明exclusion的时候只须要groupId和artifactId便可,而不须要version元素,这是由于只须要groupId和artifactId就能惟必定位依赖图中的某个依赖。换句话说,Maven解析后的依赖中,不可能出现groupId和artifactId相同,可是version不一样的两个依赖。
settings.xml
settings.xml里面是Maven的基本配置,元素比较多,逐一看一下
一、proxy
proxy表示Maven的代理,看一下写法:
<proxies> <proxy> <id>optional</id> <active>true</active> <protocol>http</protocol> <username>proxyuser</username> <password>proxypass</password> <host>proxy.host.net</host> <port>80</port> <nonProxyHosts>local.net|some.host.com</nonProxyHosts> </proxy> </proxies>
须要proxy是由于不少时候你所在的公司基于安全因素考虑,要求你使用经过安全认证的代理访问因特网。这种状况下,就须要为Maven配置HTTP代理,才能让它正常访问外部仓库,如下载所须要的资源。proxies下能够配置多个proxy元素,若是声明了多个proxy元素,则默认状况下第一个被激活的proxy会生效。active为true表示激活该代理,protocol表示使用的代理协议,固然最重要的是指定正确的主机名(host)和端口(port),若是代理服务器须要认证则配置username和password,nonProxyHost元素表示指定哪些主机名不须要代理,能够用"|"分隔多个主机名,也支持通配符"*"。
二、repository
repository表示Maven的中央仓库,由于尽管默认的远程仓库中的构件很是庞大,可是总归会有不知足咱们需求的时候,这时候就要用到别的中央仓库了。看一下写法:
<repository> <id>public</id> <name>local private nexus</name> <url>http://192.168.1.6:8081/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository>
能够声明多个repository。id必须是惟一的,尤为注意,Maven自带的中央仓库使用的id为central,若是其余仓库声明也用该id,就会覆盖中央仓库的配置。releases和snapshots比较重要,前者表示开启仓库的发布版本下载支持,后者表示关闭仓库的快照版本下载支持,这样一来,Maven就会去仓库下载发布版本的构件而不会下载快照版本的构件了。
三、server
大部分远程仓库无须认证就能够访问,可是有时候处于安全方面的因素考虑,须要提供认证信息才能访问一些远程仓库,处于安全考虑,认证信息通常只放在settings.xml中,server就是认证元素。看一下配置:
<server> <id>nexus-releases</id> <username>deployment</username> <password>deployment</password> </server>
这里的关键是id,这个id必须与须要认证的repository元素的id彻底一致才行,换句话说,正式这个id将认证信息和仓库配置联系在了一块儿。
四、mirror
若是仓库X能够提供仓库Y存储的全部内容,那么就能够认为仓库X是仓库Y的一个镜像(mirror),换句话说,任何一个能够从Y中获取到的构件够能够从X中获取到。举个例子,"http://maven.net.cn/content/groups/public/"是中央仓库"http://repo1.maven.org/maven2/"在中国的镜像,因为地理位置的因素,该镜像每每可以提供比中央仓库更快的服务,这就是为何要使用mirror的缘由。
看一下mirror的配置:
<mirror> <id>nexus</id> <name>internal nexus repository</name> <url>http://192.168.1.6:8081/nexus/content/groups/public</url> <mirrorOf>*</mirrorOf> </mirror>
该例子中,mirrof为*,表示该配置为全部中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像。另外三个元素id、name、url与通常仓库配置无异,表示该镜像仓库的惟一标识符、名称以及地址。相似的,若是该镜像须要认证,也能够基于该id配置仓库认证。