Maven POM 基礎(chǔ)配置

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)處理這種情況:

  1. 使用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,此后可以直接引用。

  1. 使用自己的倉(cāng)庫(kù)并將其部署在里面。

??????這是使用企業(yè)內(nèi)部網(wǎng)絡(luò)的公司最喜歡的一種方式,需要使每個(gè)人保持同步。此處使用的Maven命令為deploy:deploy-file,它與install:install-file使用方式類似

  1. 設(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)格:

  1. 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ī)范化為全大寫。
  2. project.x
    POM中的點(diǎn)(.)標(biāo)記路徑將包含相應(yīng)元素的值。
    例如:<project><version>1.0</version></project>與變量${project.version}相通。
  3. setting.x
    setting.xml中的點(diǎn)(.)標(biāo)記路徑將包含相應(yīng)元素的值。
    例如:<settings><offline>false</offline></settings>與變量${settings.offline}相通。
  4. Java System Properties(Java系統(tǒng)屬性):
    通過(guò)java.lang.System.getProperties()獲取到的所有屬性都可以作為POM屬性使用,例如:${java.home}
  5. x
    POM文件中的properties屬性設(shè)置的值。
    例如:<properties><someVar>value</someVar></properties>與變量${someVar}相通。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容