1 依賴
1.1 denpendency包含的元素
| 名稱 | 作用 | 備注 |
|---|---|---|
| groupId | 當(dāng)前Maven項(xiàng)目隸屬的實(shí)際項(xiàng)目 | 基本坐標(biāo) |
| artifactId | 實(shí)際項(xiàng)目中的一個(gè)Maven項(xiàng)目模塊 | 基本坐標(biāo) |
| version | 版本號 | 基本坐標(biāo) |
| type | 依賴的類型,對應(yīng)于項(xiàng)目坐標(biāo)定義的packaging(巨) | jar, war, pom,默認(rèn)是jar |
| scope | 依賴的范圍 | compile(編譯依賴范圍), test(測試依賴范圍), provided(已提供依賴范圍), runtime(運(yùn)行時(shí)依賴范圍), system(系統(tǒng)依賴范圍), import(導(dǎo)入依賴范圍), 默認(rèn)是compile |
| optional | 標(biāo)記依賴是否可選 | 可選的依賴不能被依賴傳遞 |
| exclusions | 依賴排除 | 一個(gè)exclusions可以包含一個(gè)或者多個(gè)exclusion子元素,即排除一個(gè)或者多個(gè)傳遞性依賴 |
1.2 依賴范圍 scope
| 名稱 | compile | test | runtime | 說明 |
|---|---|---|---|---|
| compile | √ | √ | √ | 對compile, test, runtime三個(gè)階段都有效 |
| test | √ | 只在test階段有效 | ||
| runtime | √ | 只在runtime階段有效 | ||
| provided | √ | √ | compile和test階段有效 | |
| system | √ | √ | 該依賴和本機(jī)系統(tǒng)綁定,所以必須使用systemPath元素顯示地指定依賴文件的路徑,使用這個(gè)依賴范圍會造成構(gòu)建的不可移植性。 | |
| import | dependencyManagement元素下才有用,該范圍的依賴通常指向一個(gè)pom,作用是把目標(biāo)pom中的dependencyManagement配置導(dǎo)入到當(dāng)前的pom,并且type配置為pom |
java程序有三種classpath,分別是compile classpath,test classpath,runtime classpath,如上表不同的依賴范圍支持不同的classpath
假設(shè)A依賴于B,B依賴于C,我們說A對于B是第一直接依賴,B對于C是第二直接依賴,A對于C是傳遞性依賴
如下圖,最左邊一列表示第一直接依賴范圍,最上面一行表示第二直接依賴范圍,中間交叉單元格表示傳遞性依賴范圍。

可以用mvn dependency:tree,可以看到各個(gè)依賴的依賴傳遞以及依賴范圍
[INFO] com.sankuai.sjst.crm:crm-common:jar:1.0.0-SNAPSHOT
[INFO] +- org.jmockit:jmockit:jar:1.9:test
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.springframework:spring-test:jar:4.2.6.RELEASE:test
[INFO] | \- org.springframework:spring-core:jar:4.2.6.RELEASE:compile
[INFO] +- com.fasterxml.jackson.core:jackson-core:jar:2.1.0:compile
[INFO] +- com.fasterxml.jackson.core:jackson-databind:jar:2.1.0:compile
[INFO] +- com.fasterxml.jackson.core:jackson-annotations:jar:2.1.0:compile
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:compile
[INFO] +- org.springframework:spring-context:jar:4.2.6.RELEASE:compile
[INFO] | +- org.springframework:spring-aop:jar:4.2.6.RELEASE:compile
[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] | +- org.springframework:spring-beans:jar:4.2.6.RELEASE:compile
[INFO] | \- org.springframework:spring-expression:jar:4.2.6.RELEASE:compile
[INFO] +- org.apache.commons:commons-lang3:jar:3.4:compile
[INFO] +- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] +- commons-io:commons-io:jar:2.3:compile
[INFO] +- com.meituan.inf:xmd-log4j2:jar:1.1.3:compile
[INFO] | +- com.meituan.inf:xmd-common-log4j2:jar:1.1.2:compile
[INFO] | | \- org.slf4j:jcl-over-slf4j:jar:1.7.2:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.7.2:compile
[INFO] | +- org.apache.logging.log4j:log4j-slf4j-impl:jar:2.3:compile
[INFO] | +- org.apache.logging.log4j:log4j-api:jar:2.3:compile
[INFO] | +- org.apache.logging.log4j:log4j-core:jar:2.3:compile
[INFO] | \- org.apache.logging.log4j:log4j-1.2-api:jar:2.3:compile
1.3 依賴原則
1.路徑最近者優(yōu)先
2.第一聲明者優(yōu)先
2 倉庫

一個(gè)構(gòu)件只有在本地倉庫中才能由其他Maven項(xiàng)目使用,構(gòu)件可以從遠(yuǎn)程倉庫中下載,也可以將本地項(xiàng)目的構(gòu)件install到本地的Maven項(xiàng)目中。
settings.xml的<localRepository>:定義本地倉庫的地址
2.1依賴查找的順序
① 在本地倉庫中搜索,如果找不到,執(zhí)行②,如果找到了則執(zhí)行其他操作。
② 在中央倉庫中搜索,如果找不到,并且有一個(gè)或多個(gè)遠(yuǎn)程倉庫已經(jīng)設(shè)置,則執(zhí)行步驟 ④,如果找到了則下載到本地倉庫中已被將來引用。
③ 如果遠(yuǎn)程倉庫沒有被設(shè)置,Maven 將簡單的停滯處理并拋出錯(cuò)誤(無法找到依賴的文件)。
④ 在一個(gè)或多個(gè)遠(yuǎn)程倉庫中搜索依賴的文件,如果找到則下載到本地倉庫已被將來引用,否則 Maven 將停止處理并拋出錯(cuò)誤(無法找到依賴的文件)。
2.2 settings.xml 和pom.xml中倉庫信息設(shè)置
依賴的下載與部署的倉庫是在pom.xml文件中的<distributionManagement>和<repository>設(shè)置的,通常訪問這些倉庫是需要認(rèn)證的,認(rèn)證信息在settings.xml<server>元素中。
pom.xml
<distributionManagement>
<repository>
<id>xxx-nexus-releases</id>
<name>xxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>xxx-nexus-snapshots</id>
<name>xxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
在settings.xml中<server>元素的id必須與pom.xml中需要認(rèn)證的<repository>的id完全一致。id將認(rèn)證信息和倉庫聯(lián)系在一起了。
<server>
<id>xxx-nexus-releases</id>
<username>xxx</username>
<password>yyyy</password>
</server>
<server>
<id>xxx-nexus-snapshots</id>
<username>xxx</username>
<password>yyy</password>
</server>
pom.xml中設(shè)置了兩個(gè)倉庫,一個(gè)是release版本的倉庫,一個(gè)是snapshots,如果release倉庫Deployment Policy是“Disable
Redeploy”,那么release版本是不允許覆蓋的。
所以當(dāng)同樣的release版本號二次發(fā)布的時(shí)候會報(bào)錯(cuò),錯(cuò)誤提示類似“Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project crm-onlinepay-client: Failed to deploy artifacts: Could not transfer artifact com.xxx.yyy:crm-onlinepay-client:jar:1.0.1 from/to xxx-nexus-releases (http://maven.xxx.com/nexus/content/repositories/releases/): Failed to transfer file: http://maven.xxx.com/nexus/content/repositories/releases/com/xxx/yyy/crm-onlinepay-client/1.0.1/crm-onlinepay-client-1.0.1.jar. Return code is: 400, ReasonPhrase: Bad Request. -> [Help 1]”
Maven2部署構(gòu)件到Nexus時(shí)出現(xiàn)的Failed to transfer file錯(cuò)誤 @周路敏
3 Maven模塊的聚合與繼承
<modules> 聲明聚合 為了快速構(gòu)建項(xiàng)目
<parent>聲明繼承 為了消除重復(fù)配置
我的onlinepay項(xiàng)目結(jié)構(gòu)

最外面層的pom.xml是聚合pom,他的packaging方式必須是pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<parent>
<groupId>com.xxx.yyyy.crm</groupId>
<artifactId>crm-parent</artifactId>
<version>1.0.4</version>
</parent>
<groupId>com.xxx.yyyy</groupId>
<artifactId>crm-onlinepay</artifactId>
<version>1.0.1</version>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<properties>
<project-client.version>1.0.1</project-client.version>
<project-web.version>1.0.1</project-web.version>
</properties>
<distributionManagement>
<repository>
<id>xxxx-nexus-releases</id>
<name>xxxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>xxxx-nexus-snapshots</id>
<name>xxx Nexus Repository</name>
<url>http://maven.xxx.com/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<modules>
<module>crm-onlinepay-client</module>
<module>crm-onlinepay-web</module>
</modules>
</project>
onlinepay-client的pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xxx.yyyy</groupId>
<artifactId>crm-onlinepay</artifactId>
<version>1.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>crm-onlinepay-client</artifactId>
<version>${project-client.version}</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.sankuai.sjst.crm</groupId>
<artifactId>crm-common</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
onlinepay-web的pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xxx.yyyy</groupId>
<artifactId>crm-onlinepay</artifactId>
<version>1.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>crm-onlinepay-web</artifactId>
<packaging>war</packaging>
<name>${project.artifactId}</name>
<version>${project-web.version}</version>
.....
</project>

3.3 反應(yīng)堆
所有模塊組成的一個(gè)構(gòu)建結(jié)構(gòu)是反應(yīng)堆,反應(yīng)堆的順序與模塊間的繼承關(guān)系和聲明順序有關(guān),如果模塊間不存在繼承關(guān)系,則反應(yīng)堆的構(gòu)建順序是聲明順序,如果存在繼承關(guān)系,則首先構(gòu)建父模塊。
crm-onlinepay-client和crm-onlinepay-web是子模塊,crm-onlinepay是父模塊

剪裁反應(yīng)堆
-am, --alse-make 同時(shí)構(gòu)建依賴于所列模塊的模塊
-amd, -alse-make-dependents 同時(shí)構(gòu)建依賴于所列模塊的模塊
-pl, --projects <arg> 構(gòu)建指定的模塊,模塊間用逗號分隔
-rf, -resume-from <arg> 從指定的模塊恢復(fù)反應(yīng)堆,也就是說從哪里開始構(gòu)建
3.4 pom中可繼承的元素
Maven繼承的目的是為了消除重復(fù),所以pom中大量的元素是可以被繼承的。
groupId:項(xiàng)目組ID,項(xiàng)目坐標(biāo)的核心元素
version: 項(xiàng)目版本, 項(xiàng)目坐標(biāo)的核心元素
description: 項(xiàng)目的描述信息
organization: 項(xiàng)目的組織信息
inceptionYear: 項(xiàng)目的創(chuàng)始年份
url: 項(xiàng)目的URL地址
developers: 項(xiàng)目開發(fā)者信息
contributors: 項(xiàng)目的貢獻(xiàn)者信息
distributionManagement: 項(xiàng)目的部署配置
issueManagement: 項(xiàng)目的缺陷跟蹤系統(tǒng)信息
ciManagement: 項(xiàng)目的持續(xù)集成系統(tǒng)信息
scm: 項(xiàng)目的系統(tǒng)信息
mailingLists: 項(xiàng)目的郵件列表信息
properties: 自定義的maven屬性
dependencies: 項(xiàng)目的依賴配置
dependencyManagement: 項(xiàng)目的依賴管理配置
repositories: 項(xiàng)目的倉庫配置
build: 包括項(xiàng)目的源碼目錄配置、輸出目錄配置、插件配置、插件管理配置等
reporting: 包括項(xiàng)目的報(bào)告輸出目錄配置、報(bào)告插件配置等
所以crm-onlinepay項(xiàng)目會繼承crm-parent里面的依賴等信息
4 靈活的構(gòu)建
Maven提供屬性,資源過濾和profile三種方式進(jìn)行靈活的構(gòu)建
4.1Maven屬性
1.內(nèi)置屬性
${basedir}表示項(xiàng)目根目錄,${version}表示項(xiàng)目版本
2.POM屬性
(使用pom屬性可以引用到pom.xml文件對應(yīng)元素的值)
${project.build.directory}表示主源碼路徑;
${project.build.sourceEncoding}表示主源碼的編碼格式;
${project.build.sourceDirectory}表示主源碼路徑;
${project.build.finalName}表示輸出文件名稱;
${project.version}表示項(xiàng)目版本,與${version}相同;
3.自定義屬性
在pom.xml文件的<properties>標(biāo)簽下定義的Maven屬性
4.settings.xml文件屬性
(與pom屬性同理,用戶使用以settings.開頭的屬性引用settings.xml文件中的XML元素值)
${settings.localRepository}表示本地倉庫的地址;
5.Java系統(tǒng)屬性
(所有的Java系統(tǒng)屬性都可以使用Maven屬性引用)
使用mvn help:system命令可查看所有的Java系統(tǒng)屬性;
System.getProperties()可得到所有的Java屬性;
${user.home}表示用戶目錄;
6.環(huán)境變量屬性
(所有的環(huán)境變量都可以用以env.開頭的Maven屬性引用)
使用mvn help:system命令可查看所有環(huán)境變量;
${env.JAVA_HOME}表示JAVA_HOME環(huán)境變量的值;
4.2 資源過濾
maven-resources-plugin的默認(rèn)行為是將項(xiàng)目主資源文件復(fù)制到主代碼編譯輸出目錄中,將測試資源文件復(fù)制到測試代碼編譯輸出目錄中,如果開啟了資源過濾,那么可以讀取資源目錄下的文件內(nèi)容,即解析資源文件中的maven屬性。
如果是web資源,則是通過maven-resources-plugin處理。
4.3 profile
可以根據(jù)環(huán)境不同選擇不同的資源配置,<activeByDefault>表示默認(rèn)激活的環(huán)境配置資源。
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<conf-dir>local</conf-dir>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<conf-dir>dev</conf-dir>
</properties>
</profile>
<profile>
<id>beta</id>
<properties>
<conf-dir>beta</conf-dir>
</properties>
</profile>
<profile>
<id>miniflow</id>
<properties>
<conf-dir>miniflow</conf-dir>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<conf-dir>test</conf-dir>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<conf-dir>prod</conf-dir>
</properties>
</profile>
<profile>
<id>staging</id>
<properties>
<conf-dir>staging</conf-dir>
</properties>
</profile>
</profiles>

可以通過命令行參數(shù) -P 加上profile的id來激活profile,多個(gè)id之間用逗號分隔。
settings.xml文件中也會有profile的配置,如果一個(gè)settings.xml中的profile被激活,它的值會覆蓋任何其它定義在pom.xml中帶有相同id的profile。
maven全局配置文件settings.xml詳解 @靜默空虛
5 超級POM
Maven約定大約配置,在$MAVEN_HONE/lib/maven-model-builder-x.x.x.jar中的org/apache/maven/model/pom-4.0.0.xml路徑下存在超級pom。每個(gè)Maven項(xiàng)目都會繼承這個(gè)超級pom,類似java中的object類,
超級pom聲明了倉庫等信息。