The Basics
??????POM文件包含關(guān)于項(xiàng)目的所有必要信息,以及在構(gòu)建項(xiàng)目過(guò)程中使用的插件配置。
??????它是一個(gè)對(duì)于"who","what","where"的聲明性表現(xiàn),而build生命周期是一個(gè)"when"和"how"的表現(xiàn)。但這并不是說(shuō)POM文件不能影響生命周期的流程,它是可以的。比如通過(guò)maven-antrun-plugin配置它可以有效的將Apache Ant任務(wù)嵌入到POM中,然而它只是一個(gè)最終的聲明。build.xml會(huì)在Ant運(yùn)行時(shí)告訴它做什么(過(guò)程中),pom只是聲明它的配置(聲明)。對(duì)于pom來(lái)說(shuō),如果某些外力導(dǎo)致生命周期跳過(guò)Ant插件,它是不會(huì)停止那些執(zhí)行中的插件的;而build.xml的任務(wù)總是依賴于之前執(zhí)行的任務(wù)。
<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>org.codehaus.mojo</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
</project>
Maven坐標(biāo)
??????groupId,artifactId,version都是必填項(xiàng)(如果從父類繼承g(shù)roupId和version,則不需要顯式地定義它們)。這三個(gè)字段很像一個(gè)地址和時(shí)間戳,它們?cè)诖鎯?chǔ)庫(kù)中標(biāo)記了一個(gè)特定的位置,充當(dāng)Maven項(xiàng)目的坐標(biāo)系統(tǒng)。
- groupId:它在組織或項(xiàng)目中通常是唯一的。
??????groupId并不是必須使用"."分隔(如junit),另外使用"."標(biāo)記的groupId也不一定要與項(xiàng)目的包結(jié)構(gòu)相對(duì)應(yīng)(不過(guò)建議與包結(jié)構(gòu)對(duì)應(yīng))。當(dāng)在存儲(chǔ)倉(cāng)庫(kù)中存儲(chǔ)時(shí),group的行為和在操作系統(tǒng)中的Java包結(jié)構(gòu)非常相似。這些"."被操作系統(tǒng)特定的目錄分隔符替換(如UNIX中的"/")使基礎(chǔ)倉(cāng)庫(kù)變成了相對(duì)的目錄結(jié)構(gòu)。在上面的例子中org.codehaus.mojo組被存儲(chǔ)于$M2_REPO/org/codehaus/mojo目錄下。
- artifactId:它通常是項(xiàng)目已知的名稱。
??????artifactId和groupId一起創(chuàng)建了一個(gè)key值,用來(lái)區(qū)別于世界上其他的項(xiàng)目。它與groupId一起定義了artifact在存儲(chǔ)倉(cāng)庫(kù)中的位置。在上面的例子中my-project存儲(chǔ)于$M2_REPO/org/codehaus/mojo/my-project目錄。
- version:用來(lái)指定項(xiàng)目的版本。
??????groupId和artifactId可以表示單個(gè)項(xiàng)目,但它們無(wú)法描述我們正在討論的是該項(xiàng)目的哪一種形式。比如我們是想使用2018年的junit:junit(4.12版本)還是2007年的junit:junit(3.8.2版本)?簡(jiǎn)而言之:代碼更改,應(yīng)該對(duì)這些更改進(jìn)行版本控制,并且此元素可以使這些版本保持一致。同樣的,它也被用于存儲(chǔ)倉(cāng)庫(kù)中用來(lái)區(qū)分不同的版本。在上面的例子中my-project最終存儲(chǔ)于$M2_REPO/org/codehaus/mojo/my-project/1.0目錄中。
packaging
??????用來(lái)聲明項(xiàng)目的打包方式。若沒(méi)有聲明該部分則默認(rèn)打包方式為jar。當(dāng)前packaging的值有:pom,jar,maven-plugin,ejb,war,ear,rar
POM依賴關(guān)系
??????Maven一個(gè)強(qiáng)大的方面是它對(duì)項(xiàng)目關(guān)系的處理,包括依賴項(xiàng)和傳遞依賴項(xiàng)、繼承和聚合(多model的項(xiàng)目)。依賴項(xiàng)管理的傳統(tǒng)就是除了最瑣碎的項(xiàng)目之外,其他項(xiàng)目都是一團(tuán)糟。隨著依賴樹變得龐大而復(fù)雜,"Jarmageddon"很快就出現(xiàn)了。接下來(lái)是"Jar Hell",在Jar Hell中,一個(gè)系統(tǒng)上依賴的版本與使用它開發(fā)的版本是不相等的,要么是給出的版本是錯(cuò)誤的,要么是名稱類似的Jar之間的版本沖突。Maven通過(guò)一個(gè)公共的本地存儲(chǔ)庫(kù)解決了這兩個(gè)問(wèn)題,從這個(gè)存儲(chǔ)庫(kù)可以正確地鏈接項(xiàng)目、版本等。
Dependencies
??????POM的基礎(chǔ)是其dependency列表。大多數(shù)項(xiàng)目依賴于其他項(xiàng)目才能成功build和運(yùn)行。Maven會(huì)在編譯時(shí)下載和鏈接這些dependency和它們依賴的其他目標(biāo)。
- Maven優(yōu)點(diǎn):幫助你管理所依賴項(xiàng)目的相關(guān)依賴,使你只需要關(guān)注自己項(xiàng)目所需的依賴關(guān)系即可。
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<dependencies>
<dependency>
<!-- 依賴的group ID -->
<groupId>org.apache.maven</groupId>
<!-- 依賴的artifact ID -->
<artifactId>maven-artifact</artifactId>
<!-- 依賴的版本號(hào) -->
<version>3.8.1</version>
<!-- 依賴類型,默認(rèn)類型是jar。
它通常表示依賴的文件的擴(kuò)展名,但也可以被映射成另外一個(gè)擴(kuò)展名或分類器。
type經(jīng)常和使用的打包方式對(duì)應(yīng)(也有例外)。一些類型的例子:jar,war,ejb-client和test-jar。
如果設(shè)置extensions為true,就可以在plugin里定義新的類型。 -->
<type>jar</type>
<!-- 依賴的分類器。
分類器可以區(qū)分屬于同一個(gè)POM,但不同構(gòu)建方式的artifact。分類器名被附加到version后面。
例如,如果你想要構(gòu)建兩個(gè)單獨(dú)的artifact成JAR,一個(gè)使用Java1.4編譯器,另一個(gè)使用Java6編譯器,
就可以使用分類器來(lái)生成兩個(gè)單獨(dú)的JAR構(gòu)件。 -->
<classifier></classifier>
<!-- 依賴范圍。在項(xiàng)目發(fā)布過(guò)程中,幫助決定哪些構(gòu)件被包括進(jìn)來(lái)。欲知詳情請(qǐng)參考依賴機(jī)制。
- compile :默認(rèn)范圍,用于編譯
- provided:類似于編譯,但支持你期待jdk或者容器提供,類似于classpath
- runtime: 在執(zhí)行時(shí)需要使用
- test: 用于test任務(wù)時(shí)使用
- system: 需要外在提供相應(yīng)的元素。通過(guò)systemPath來(lái)取得
- systemPath: 僅用于范圍為system。提供相應(yīng)的路徑
- optional: 當(dāng)項(xiàng)目自身被依賴時(shí),標(biāo)注依賴是否傳遞。用于連續(xù)依賴時(shí)使用 -->
<scope>test</scope>
<!-- 僅供system范圍使用。
注意,不鼓勵(lì)使用這個(gè)元素,并且在新的版本中該元素可能被覆蓋掉。
該元素為依賴規(guī)定了文件系統(tǒng)上的路徑,必須是絕對(duì)路徑。
推薦使用屬性匹配絕對(duì)路徑,如${java.home}. -->
<systemPath></systemPath>
<!-- 當(dāng)計(jì)算傳遞依賴時(shí),從依賴構(gòu)件列表里,列出被排除的依賴構(gòu)件集。
即告訴maven你只依賴指定的項(xiàng)目,不依賴項(xiàng)目的依賴。此元素主要用于解決版本沖突問(wèn)題 -->
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
<!-- 可選依賴,如果你在項(xiàng)目B中把C依賴聲明為可選,就需要在依賴于B的項(xiàng)目中顯式的引用對(duì)C的依賴。
可選依賴阻斷依賴的傳遞性。 -->
<optional>true</optional>
</dependency>
...
</dependencies>
...
</project>
- groupId,artifactId,version:
??????此三元組用于及時(shí)計(jì)算特定項(xiàng)目的Maven坐標(biāo),并將其劃分為該項(xiàng)目的依賴項(xiàng)。這個(gè)計(jì)算的目的是選擇一個(gè)匹配所有依賴聲明的版本(因?yàn)橐蕾囀莻鬟f的,對(duì)于同一個(gè)artifact可能有多個(gè)dependency聲明)。groupId & artifactId:直接指向此依賴的坐標(biāo);version:依賴項(xiàng)版本必要說(shuō)明,用于計(jì)算依賴項(xiàng)的有效版本。
??????由于依賴性是由Maven坐標(biāo)描述的,所以項(xiàng)目只能依賴于Maven的artifact工作,這迫使你只能依賴那些Maven可以管理的dependency。
??????有時(shí)候無(wú)法從Maven中央倉(cāng)庫(kù)下載一個(gè)項(xiàng)目,比如一個(gè)項(xiàng)目依賴了一個(gè)具有閉源許可證的JAR包,閉源的JAR包Maven中央倉(cāng)庫(kù)是不會(huì)存儲(chǔ)的。有三種方法來(lái)處理這種情況:
- 使用install插件,在本地install這些依賴(此方法是最簡(jiǎn)單的推薦方法)。例子:
mvn install:install-file -Dfile=non-maven-proj.jar -DgroupId=some.group -DartifactId=non-maven-proj -Dversion=1 -Dpackaging=jar
注意:此處仍然需要一個(gè)地址。只有第一次需要使用命令行,然后install插件會(huì)根據(jù)給定的地址創(chuàng)建一個(gè)POM,此后可以直接引用。
- 使用自己的倉(cāng)庫(kù)并將其部署在里面。
??????這是使用企業(yè)內(nèi)部網(wǎng)絡(luò)的公司最喜歡的一種方式,需要使每個(gè)人保持同步。此處使用的Maven命令為deploy:deploy-file,它與install:install-file使用方式類似
- 設(shè)置這個(gè)依賴的scope為system并且定義一個(gè)systemPath。但是此方式并推薦,主要為了引出以下屬性:
- classifier-依賴的分類器:
??????classifier用于區(qū)分從同一個(gè)POM構(gòu)建的但內(nèi)容不同的artifact。它是一些可選的任意字符串,如果存在則被附加到artifact的版本號(hào)之后。
??????例如:一個(gè)項(xiàng)目提供了一個(gè)針對(duì)JRE1.5的artifact,但同時(shí)也仍然支持JRE1.4的artifact。這時(shí)就可以使用classifier標(biāo)記一個(gè)artifact為jdk15,另一個(gè)為jdk14,這樣使用者就可以選擇使用哪一個(gè)。另外一個(gè)應(yīng)用場(chǎng)景就是將次要的artifact添加到項(xiàng)目的主artifact上。如果瀏覽Maven中央倉(cāng)庫(kù)就會(huì)注意到classifier"sources"和"javadoc"被用于部署項(xiàng)目源代碼和API文檔以及打包的類文件。
- type-依賴的類型:
??????對(duì)應(yīng)于依賴的類型,默認(rèn)為jar。它通常表示dependency文件的拓展名,也可以將type映射到不同的extension和classifier。type的值通常對(duì)應(yīng)于packaging使用的值,但是也有例外,如:jar,ejb-client和test-jar,詳情參見:http://maven.apache.org/ref/current/maven-core/artifact-handlers.html。
PS:新的type可以在extensions為true的plugins中定義。
-
scope-依賴的作用域:
此屬性指的是手頭任務(wù)(編譯、運(yùn)行和測(cè)試等)的類路徑,以及如何限制依賴的傳遞性。有五個(gè)值可用:- compile:默認(rèn)作用范圍,當(dāng)未指定時(shí)默認(rèn)使用該值。編譯期依賴可以在所有的類路徑中使用,并且這些依賴關(guān)系可以被傳播到其他項(xiàng)目。
- provided:它與compile很相似,但是表示只希望在JDK或容器在運(yùn)行時(shí)提供該依賴。它只在編譯和測(cè)試的類路徑上有效,并且是不傳遞的。
- runtime:該作用域表示編譯期不需要該dependency,但是執(zhí)行時(shí)需要。它只在運(yùn)行時(shí)和測(cè)試的類路徑上有效,編譯的類路徑中不存在。
- test:該作用域表示該dependency正常情況下是非必須的。它只在測(cè)試編譯和執(zhí)行階段生效,是不傳遞的。
- system:該作用域與provided類似,不過(guò)system表示需要顯式的提供它包含的JAR包。該artifact總是可用的,但是不是從存儲(chǔ)倉(cāng)庫(kù)中查找的。
systemPath-依賴的系統(tǒng)路徑:
??????當(dāng)且僅當(dāng)dependency的scope值為system時(shí)有效。如果scope的值不是system而設(shè)置了systemPath那么將build失敗。該值指向的路徑必須是絕對(duì)路徑,因此建議使用屬性來(lái)指定特定于機(jī)器的路徑如 ${java.home}/lib。因?yàn)榧俣╯ystem作用域的依賴已經(jīng)被安裝了,所以Maven不會(huì)在存儲(chǔ)倉(cāng)庫(kù)中檢查該項(xiàng)目,而是檢查該文件是否存在,如果不存在則Maven將build失敗并且建議手動(dòng)下載和安裝它。
- optional-依賴的可選項(xiàng):
??????當(dāng)不可能(無(wú)論出于何種原因)將項(xiàng)目分割為子模塊時(shí),將使用optional依賴項(xiàng)。其思想是,一些依賴項(xiàng)僅用于項(xiàng)目中的某些功能,如果不使用該功能,就不需要這些依賴項(xiàng)。理想情況下,這樣的功能應(yīng)該劃分為依賴于核心功能項(xiàng)目的子模塊,這個(gè)新的子項(xiàng)目將只有非可選的dependency。然而,由于項(xiàng)目不能被分割(無(wú)論出于什么原因),這些依賴項(xiàng)被聲明為可選的。如果用戶希望使用與可選依賴項(xiàng)相關(guān)的功能,則必須在自己的項(xiàng)目中重新聲明該可選依賴項(xiàng)。這不是處理這種情況的最好方法,但是可選的依賴項(xiàng)(optional)和依賴項(xiàng)排除(exclusion)都是權(quán)宜之計(jì)。
??????應(yīng)用場(chǎng)景:optional依賴項(xiàng)可以節(jié)省空間和內(nèi)存,另外它們可以防止有問(wèn)題的jar(違反許可協(xié)議或?qū)е骂惵窂絾?wèn)題)被綁定到WAR、EAR、fat jar或類似的jar中。
??????optional的值只支持true或者false
- exclusions-依賴的排除:
??????exclusions指定了一個(gè)依賴項(xiàng),它告訴Maven不要將其包含在當(dāng)前依賴項(xiàng)中(這是由于依賴的傳遞性)。比如maven-embedder需要使用maven-core但是我們不希望使用它或者它的依賴項(xiàng),那么就可以將其排除:
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>2.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</exclusion>
</exclusions>
</dependency>
...
</dependencies>
...
</project>
??????有時(shí)exclusions也可以用來(lái)剪掉依賴的傳遞關(guān)系。一個(gè)dependency可能指定了錯(cuò)誤的作用域,或者與你項(xiàng)目中的其他依賴項(xiàng)沖突。使用通配符可以很容易地排除所有依賴項(xiàng)的傳遞關(guān)系。下面的例子表示你需要使用maven-embedder但是你希望自己管理它的依賴項(xiàng),所以就排除了其全部的傳遞依賴:
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
...
</dependencies>
...
</project>
exclusions中包含一個(gè)或多個(gè)exclusion,每一個(gè)exclusion都包含groupId和artifactId用以表示要排除的依賴。
Inheritance -- 繼承
??????父項(xiàng)目和聚合項(xiàng)目需要的packaging類型是pom。packaging的類型定義了綁定到一組生命周期階段的目標(biāo)。例如,如果packaging是jar,那么打包(package)階段將執(zhí)行jar:jar目標(biāo)。父POM中的大多數(shù)元素都可以被其孩子繼承,包括:
- groupId
- version
- description
- url
- inceptionYear(項(xiàng)目創(chuàng)建年份,4位數(shù)字。當(dāng)產(chǎn)生版權(quán)信息時(shí)需要使用這個(gè)值)
- organization(項(xiàng)目開發(fā)者/貢獻(xiàn)者所屬組織)
- licenses
- developers(項(xiàng)目開發(fā)者信息)
- contributors(項(xiàng)目貢獻(xiàn)者信息)
- mailingLists(項(xiàng)目相關(guān)郵件列表信息)
- scm(Source Control Management 用來(lái)配置代碼庫(kù)以供Maven Web站點(diǎn)和其他插件使用)
- issueManagement(項(xiàng)目的問(wèn)題管理系統(tǒng))
- ciManagement(項(xiàng)目持續(xù)集成信息)
- properties(以值替代名稱,Properties可以在整個(gè)POM中使用,也可以作為觸發(fā)條件)
- dependencyManagement(繼承自該項(xiàng)目的所有子項(xiàng)目的默認(rèn)依賴信息。這部分的依賴信息不會(huì)被立即解析,而是當(dāng)子項(xiàng)目聲明一個(gè)依賴)
- dependencies
- repositories(發(fā)現(xiàn)dependency和exclusion的遠(yuǎn)程倉(cāng)庫(kù)列表)
- pluginRepositories(發(fā)現(xiàn)plugin的遠(yuǎn)程倉(cāng)庫(kù)列表,這些插件用于build和report)
- build
- plugin executions with matching ids
- plugin configuration
- etc.
- reporting(該元素描述使用report插件產(chǎn)生報(bào)表的規(guī)范。當(dāng)用戶執(zhí)行“mvn site”,這些報(bào)表就會(huì)運(yùn)行。 在頁(yè)面導(dǎo)航欄能看到所有報(bào)表的鏈接。)
- profiles(在列的項(xiàng)目構(gòu)建profile,如果被激活,會(huì)修改build)
不會(huì)被繼承的元素:
artifactId
name
-
prerequisites(描述了這個(gè)項(xiàng)目build環(huán)境中的前提條件)
<!-- 描述了這個(gè)項(xiàng)目構(gòu)建環(huán)境中的前提條件。 --> <prerequisites> <!-- 構(gòu)建該項(xiàng)目或使用該插件所需要的Maven的最低版本 --> <maven></maven> </prerequisites>
Super POM
??????類似于面向?qū)ο缶幊讨袑?duì)象的繼承,拓展父pom的那些poms繼承了來(lái)自父級(jí)的一些值。另外,正如Java中的對(duì)象最終都是繼承自java.lang.Object一樣,所有的項(xiàng)目的對(duì)象模型都是繼承自一個(gè)基礎(chǔ)的pom--Super POM。下面的片段是Maven 3.5.4的Super POM:
<project>
<modelVersion>4.0.0</modelVersion>
<!-- 發(fā)現(xiàn)dependency和exclusion的遠(yuǎn)程倉(cāng)庫(kù)列表 -->
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<!-- 發(fā)現(xiàn)插件的遠(yuǎn)程倉(cāng)庫(kù)列表,用于build和report -->
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
<build>
<directory>${project.basedir}/target</directory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
<pluginManagement>
<!-- NOTE: These plugins will be removed from future versions of the super POM -->
<!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<outputDirectory>${project.build.directory}/site</outputDirectory>
</reporting>
<profiles>
<!-- NOTE: The release profile will be removed from future versions of the super POM -->
<profile>
<!-- 構(gòu)建配置的唯一標(biāo)識(shí)符。即用于命令行激活,也用于在繼承時(shí)合并具有相同標(biāo)識(shí)符的profile -->
<id>release-profile</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<inherited>true</inherited>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Dependency Management -- 依賴管理
除了繼承某些頂級(jí)元素外,父元素還可以為子POM們傳遞依賴項(xiàng)配置值,其中一個(gè)父元素就是dependencyManagement。
- dependencyManagement被用于幫助POM管理所有孩子節(jié)點(diǎn)的依賴信息。
例子:假設(shè)父工程my-project使用dependencyManagement定義了一個(gè)依賴"junit:junit:4.12",然后繼承了該工程的一個(gè)pom只設(shè)置了 groupId=junit 和 artifactId=junit 那么Maven會(huì)通過(guò)其父pom的version將其補(bǔ)全。 - 這種方式的優(yōu)點(diǎn):你可以在一個(gè)核心位置設(shè)置依賴信息,然后將其傳播給繼承了它的pom。
- 注意:從傳遞依賴合并而來(lái)的artifact的version和scope也由依賴項(xiàng)管理部分中的版本規(guī)范控制,這可能會(huì)導(dǎo)致意想不到的后果。例子:你的項(xiàng)目有兩個(gè)依賴項(xiàng) dep1 和 dep2,同時(shí)dep2也依賴dep1,并且需要一個(gè)特定的版本來(lái)運(yùn)行。如果此時(shí)你使用dependencyManagement來(lái)指定一個(gè)較舊的版本,那么dep2將被迫使用舊版本運(yùn)行,就會(huì)失敗。因此你必須檢查整個(gè)依賴樹(mvn dependency:tree)以避免此類問(wèn)題。
Aggregation(Multi-Module)-- 聚合
??????一個(gè)具有modules的項(xiàng)目被稱為多模塊或聚合項(xiàng)目。modules是POM列出的項(xiàng)目,并作為一個(gè)組執(zhí)行。packaging為pom的項(xiàng)目可以聚合構(gòu)建modules中列出的項(xiàng)目,這些模塊是這些項(xiàng)目的目錄或pom文件的相對(duì)路徑。
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<packaging>pom</packaging>
<modules>
<module>my-project</module>
<module>another-project</module>
<module>third-project/pom-example.xml</module>
</modules>
</project>
??????在modules列表中不必考慮模塊間的依賴關(guān)系,modules中的列表順序也是不重要的。Maven會(huì)對(duì)這些模塊進(jìn)行拓展排序,這樣dependency總是在依賴它的modules之前構(gòu)建。
Inheritance(繼承) VS Aggregation(聚合)
??????聚合和繼承都可以通過(guò)一個(gè)單一的高層次的POM來(lái)動(dòng)態(tài)的控制build。你經(jīng)常可以看到一個(gè)項(xiàng)目既有parents又有繼承。例如,整個(gè)Maven核心通過(guò)一個(gè)基礎(chǔ)POM org.apache.maven:maven 運(yùn)行,所以在build這個(gè)Maven工程的時(shí)候可以執(zhí)行一個(gè)簡(jiǎn)單的命令:mvn compile。但是聚合項(xiàng)目和父項(xiàng)目都是POM工程,他們不是一個(gè)也不一樣,千萬(wàn)不要混淆。一個(gè)POM可以被繼承但不一定具有任何聚合的modules。相反的,一個(gè)POM工程也可以聚合不從它繼承的項(xiàng)目。
Properties
??????properties是了解POM基礎(chǔ)知識(shí)的最后一個(gè)必選項(xiàng)。Maven properties和Ant中的properties類似,是占位符的值。它們的值可以通過(guò)使用${X}符號(hào)在POM中的任何地方訪問(wèn),其中X是屬性?;蛘咚鼈?strong>可以作為默認(rèn)值被插件使用,例如:
<project>
...
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
...
</project>
它們有五種不同的風(fēng)格:
- env.X
在變量前面加上"env."將返回shell的環(huán)境變量。例如${env.PATH}包含PATH環(huán)境變量。注意:雖然環(huán)境變量本身在Windows上是大小寫不敏感的,但是對(duì)屬性的查找是大小寫敏感的。換句話說(shuō),當(dāng)Windows shell為%PATH%和%Path%返回相同的值時(shí),Maven會(huì)區(qū)分${env.PATH}和$ {env.Path}。為了保證可靠性,環(huán)境變量的名稱被規(guī)范化為全大寫。 - project.x
POM中的點(diǎn)(.)標(biāo)記路徑將包含相應(yīng)元素的值。
例如:<project><version>1.0</version></project>與變量${project.version}相通。 - setting.x
setting.xml中的點(diǎn)(.)標(biāo)記路徑將包含相應(yīng)元素的值。
例如:<settings><offline>false</offline></settings>與變量${settings.offline}相通。 - Java System Properties(Java系統(tǒng)屬性):
通過(guò)java.lang.System.getProperties()獲取到的所有屬性都可以作為POM屬性使用,例如:${java.home} - x
POM文件中的properties屬性設(shè)置的值。
例如:<properties><someVar>value</someVar></properties>與變量${someVar}相通。