Maven pom.xml 文件詳解

POM 代表“Project Object Model”霜大。它是 Maven 項(xiàng)目的 XML 表示形式,保存在名為 pom.XML 的文件中纹腌。一個(gè)項(xiàng)目不僅僅是包含代碼的文件集合材原,還包含配置文件,以及所涉及的開發(fā)人員和他們扮演的角色、缺陷跟蹤系統(tǒng)、組織和許可證、項(xiàng)目所在地的 URL均澳、項(xiàng)目的依賴關(guān)系,以及所有其他為賦予代碼生命而發(fā)揮作用的小部分符衔。事實(shí)上找前,在 Maven 世界中,項(xiàng)目根本不需要包含任何代碼判族,只需要一個(gè) pom.xml躺盛。

下面是 pom.xml 文件中的元素列表。請(qǐng)注意五嫂,modelVersion 必須為 4.0.0颗品。這是當(dāng)前唯一受支持的 POM 版本,并且始終是必需的沃缘。

<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>
 
  <!-- The Basics -->
  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <packaging>...</packaging>
  <dependencies>...</dependencies>
  <parent>...</parent>
  <dependencyManagement>...</dependencyManagement>
  <modules>...</modules>
  <properties>...</properties>
 
  <!-- Build Settings -->
  <build>...</build>
  <reporting>...</reporting>
 
  <!-- More Project Information -->
  <name>...</name>
  <description>...</description>
  <url>...</url>
  <inceptionYear>...</inceptionYear>
  <licenses>...</licenses>
  <organization>...</organization>
  <developers>...</developers>
  <contributors>...</contributors>
 
  <!-- Environment Settings -->
  <issueManagement>...</issueManagement>
  <ciManagement>...</ciManagement>
  <mailingLists>...</mailingLists>
  <scm>...</scm>
  <prerequisites>...</prerequisites>
  <repositories>...</repositories>
  <pluginRepositories>...</pluginRepositories>
  <distributionManagement>...</distributionManagement>
  <profiles>...</profiles>
</project>

POM 包含關(guān)于項(xiàng)目的所有必要信息躯枢,以及構(gòu)建過程中使用的插件配置。它是“who”槐臀、“what”和“where”的聲明性表示锄蹂,而構(gòu)建生命周期是“when”和“how”。這并不是說 POM 不能影響生命周期的流程——它可以水慨。例如得糜,通過配置 maven-antrun-plugin 插件,可以將 Apache Ant 任務(wù)嵌入 POM 中晰洒。然而朝抖,這最終是一個(gè)聲明。雖然 Ant 的 build.xml 精確地告訴 Ant 在運(yùn)行時(shí)要做什么谍珊,但 POM 聲明了它的配置治宣。如果某些外力導(dǎo)致生命周期跳過 Ant 插件的執(zhí)行,它不會(huì)阻止其他插件的執(zhí)行砌滞。這與 build.xml 文件不同侮邀,在 build.xml 文件中,任務(wù)幾乎總是依賴于它之前執(zhí)行的行贝润。

Maven 坐標(biāo)

上面定義的 POM 是 Maven 允許的最小值绊茧。Maven 中的坐標(biāo)元素必須包含 groupIdartifactId打掘、version华畏。如果 groupIdversion 是從其父級(jí)繼承的鹏秋,則不需要顯式定義

<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.sonatype.nexus</groupId>
  <artifactId>nexus-indexer</artifactId>
  <version>2.0.0</version>
</project>
  • groupId:該元素定義當(dāng)前 Maven 項(xiàng)目所隸屬的實(shí)際項(xiàng)目亡笑,在一個(gè)實(shí)際項(xiàng)目中通常是獨(dú)一無(wú)二的拼岳。

    首先,Maven 項(xiàng)目和實(shí)際項(xiàng)目不一定是一對(duì)一的關(guān)系况芒。比如 SpringFramework 這一實(shí)際項(xiàng)目,其下對(duì)應(yīng)的 Maven 項(xiàng)目會(huì)有很多叶撒,如 spring-core绝骚、spring-context 等。這是由于 Maven 中模塊的概念祠够,因此压汪,一個(gè)實(shí)際項(xiàng)目往往會(huì)被劃分成很多模塊。groupId 不應(yīng)該對(duì)應(yīng) Maven 項(xiàng)目所隸屬的組織機(jī)構(gòu)或公司古瓤。原因很簡(jiǎn)單止剖,一個(gè)組織機(jī)構(gòu)或公司下會(huì)有很多實(shí)際項(xiàng)目,如果 groupld 只定義到組織機(jī)構(gòu)或公司級(jí)別落君,那么 artifactld 只能定義實(shí)際項(xiàng)目級(jí)別穿香,那么 Maven 項(xiàng)目級(jí)別(模塊)這個(gè)層次將難以定義;

    其次绎速,groupId 不一定使用點(diǎn)號(hào)表示法皮获,例如 junit 項(xiàng)目。請(qǐng)注意纹冤,以點(diǎn)號(hào)表示的 groupId 不必與項(xiàng)目包含的包結(jié)構(gòu)相對(duì)應(yīng)洒宝。然而,這是一個(gè)值得遵循的良好實(shí)踐萌京。

    最后雁歌,groupld 的表示方式與 Java 包名的表示方式類似,通常與倒序的域名一一對(duì)應(yīng)知残。上例中靠瞎,groupld 為 org.sonatype.nexus,org.sonatype 表示 Sonatype 公司建立的一個(gè)非盈利性組織橡庞,nexus 表示Nexus 這一實(shí)際項(xiàng)目较坛,該 groupId 與倒序的 nexus.sonatype.org 域名對(duì)應(yīng)。當(dāng)存儲(chǔ)在倉(cāng)庫(kù)中時(shí)扒最,groupId 中的點(diǎn)號(hào)被特定于操作系統(tǒng)的目錄分隔符(如 Unix 中的 /)所取代丑勤,該分隔符將成為倉(cāng)庫(kù)基準(zhǔn)目錄下的相對(duì)目錄結(jié)構(gòu)。例如吧趣,org.sonatype.nexus 組位于倉(cāng)庫(kù)中的 $M2_REPO/org/sonatype/nexus 目錄中法竞。

  • artifactId:該元素定義實(shí)際項(xiàng)目中的一個(gè) Maven 項(xiàng)目(模塊)耙厚,推薦的做法是使用實(shí)際項(xiàng)目名作為 artifactId 的前綴。比如上例中的 artifactIdnexus-indexer, 使用了實(shí)際項(xiàng)目名 nexus 作為前綴岔霸,這樣做的好處是方便尋找實(shí)際工件薛躬。在默認(rèn)情況下,Maven 生成的工件呆细,其文件名會(huì)以 artifactId 作為開頭型宝,如 nexus-indexer-2. 0.0.jar,使用實(shí)際項(xiàng)目名稱作為前綴之后絮爷,就能方便從一個(gè) lib 文件夾中找到某個(gè)項(xiàng)目的一組構(gòu)件趴酣。考慮有 5 個(gè)項(xiàng)目坑夯,每個(gè)項(xiàng)目都有一個(gè)core模塊岖寞,如果沒有前綴,我們會(huì)看到很多 core-1.2. jar 這樣的文件柜蜈,加上實(shí)際項(xiàng)目名前綴之后仗谆,便能很容易區(qū)分 foo-core-1.2.jar、bar-core-1.2.jar 等淑履。artifactId 完全定義了工件在倉(cāng)庫(kù)中的存儲(chǔ)位置隶垮。上述的項(xiàng)目位于倉(cāng)庫(kù)中的 $M2_REPO/org/sonatype/nexus/nexus-indexer 目錄中。

  • version:該元素定義 Maven 項(xiàng)目當(dāng)前所處的版本鳖谈,如上例中 nexus-indexer 的版本是 2.0.0岁疼。 需要注意的是,Maven 定義了一套完成的版本規(guī)范捷绒,以及快照(SNAPSHOT)的概念。version 還用于將倉(cāng)庫(kù)中的某個(gè)工件各版本分離開來鸠信,例如琳袄,上述項(xiàng)目 2.0.0 版本的工件位于倉(cāng)庫(kù)中的 $M2_REPO/org/sonatype/nexus/nexus-indexer 目錄中秃嗜。

現(xiàn)在我們有了 groupId:artifactId:version 的地址結(jié)構(gòu)取劫,還有一個(gè)標(biāo)準(zhǔn)的 packaging 元素用來定義 Maven 項(xiàng)目的打包類型迅栅。當(dāng)未聲明任何打包類型時(shí)殊校,Maven 假定的默認(rèn)打包類型為 jar。該元素當(dāng)前支持的值有:pom读存、jar为流、maven-pluginejb让簿、war敬察、earrar尔当。

<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">
  ...
  <packaging>war</packaging>
  ...
</project>

依賴

POM 的基石是其依賴項(xiàng)列表莲祸。大多數(shù)項(xiàng)目依賴其他項(xiàng)目來正確地構(gòu)建和運(yùn)行。在編譯時(shí)或執(zhí)行其他需要需要這些依賴項(xiàng)的目標(biāo)時(shí)椭迎,Maven 會(huì)下載并鏈接這些依賴項(xiàng)锐帜。作為額外的好處,Maven 會(huì)引入這些依賴項(xiàng)的依賴項(xiàng)(即使沒有顯式聲明)畜号,可傳遞依賴項(xiàng)抹估,允許您的列表只關(guān)注項(xiàng)目所需的依賴項(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>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <classifier>jar</classifier>
      <type>jar</type>
      <scope>test</scope>
      <systemPath>test</systemPath>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
  ...
</project>
  • groupId弄兜、artifactId药蜻、version:該三個(gè)元素用于計(jì)算特定項(xiàng)目的 Maven 坐標(biāo),并將其當(dāng)作為該項(xiàng)目的依賴項(xiàng)替饿。由于可傳遞的依賴項(xiàng)语泽,同一工件可以有多個(gè)依賴項(xiàng)聲明。由于依賴關(guān)系由 Maven 坐標(biāo)描述视卢,這意味著當(dāng)前項(xiàng)目只能依賴 Maven 的依賴項(xiàng)來管理工件及其依賴關(guān)系踱卵。不幸的是,有時(shí)無(wú)法從 Maven 中央倉(cāng)庫(kù)下載項(xiàng)目。例如惋砂,一個(gè)項(xiàng)目可能依賴于一個(gè)擁有封閉源代碼許可的 jar妒挎,該許可不允許它上傳到中央存儲(chǔ)庫(kù)中。有三種方法可以處理這種情況西饵。

    1. 使用maven-install-plugin 插件的 install:install-file 目標(biāo)來將擁有封閉源代碼許可的 jar 安裝到本地倉(cāng)庫(kù)中酝掩。例如:

      mvn install:install-file -Dfile=D:\JavaDev\myapp.jar -DgroupId=com.myapp -DartifactId=myapp-core -Dversion=1.0.0 -Dpackaging=jar
      
    2. 使用maven-deploy-plugin 插件的 deploy:deploy-file 的目標(biāo)來該擁有封閉源代碼許可的 jar 文件部署到您私有的 Maven 倉(cāng)庫(kù)中。這樣眷柔,所以可以連接到該倉(cāng)庫(kù)的開發(fā)電腦都可以像使用正常依賴那樣使用該依賴了期虾。

    3. 將依賴項(xiàng)的 scope 子元素值設(shè)置為 system 并定義一個(gè)同級(jí)的 systemPath 子元素,然后指定 systemPath 子元素的值為該擁有封閉源代碼許可的 jar 文件的本地路徑驯嘱。但是镶苞,不建議這樣做。

  • classifier該元素用來幫助定義構(gòu)建輸出的一些附屬構(gòu)件鞠评。它是一些可選的任意字符串茂蚓,如果存在的話,會(huì)被附加到版本號(hào)后面的工件名稱上剃幌。如上例中的主構(gòu)件是 nexus-indexer-2.0.0.jar煌贴,該項(xiàng)目可能還會(huì)通過使用一些插件生成如 nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar 這樣的一些附屬構(gòu)件锥忿,其包含了 Java 文檔和源代碼。這時(shí)候怠肋,javadoc 和 sources 就是這兩個(gè)附屬構(gòu)件的 classifier敬鬓。 這樣,附屬構(gòu)件也就擁有了自己唯一的坐標(biāo)笙各《ご穑考慮這樣一個(gè)項(xiàng)目,它提供了一個(gè)針對(duì) Java 11 的工件杈抢,但同時(shí)也是一個(gè)仍然支持 Java 1.8 的工件数尿。第一個(gè)工件可以指定 classifier 值為 jdk11,第二個(gè)工件可以指定 classifier 值為 jdk8惶楼,這樣用戶就可以根據(jù)需要選擇使用哪一個(gè)右蹦。注意,不能直接定義項(xiàng)目的 classifier, 因?yàn)楦綄贅?gòu)件不是項(xiàng)目直接默認(rèn)生成的歼捐,而是由附加的插件幫助生成何陆。

  • type指定所選依賴項(xiàng)的類型,大部分情況下不需要聲明該元素豹储,默認(rèn)為 jar贷盲。雖然它通常表示依賴項(xiàng)文件名上的擴(kuò)展名,但情況并非總是這樣:類型可以映射到不同的擴(kuò)展名和 classifier剥扣。類型通常與依賴項(xiàng)所的 packaging 元素值相對(duì)應(yīng)巩剖,盡管情況并非總是如此铝穷。新類型可以由將 extensions 設(shè)置為 true 的插件來定義,因此佳魔,下面的列表這不是一個(gè)完整的列表曙聂。工件處理程序?yàn)楣ぜ系拿總€(gè)依賴類型定義信息(classifierextension吃引、language)以及如何管理該依賴項(xiàng)(添加到類路徑筹陵,包含到依賴中)。某些工件處理程序默認(rèn)在 META-INF/plexus/artifact-handlers.xml 中配置:

    type classifier extension packaging language added to classpath includesDependencies
    pom = type = type none
    jar = type = type java true
    test-jar tests jar jar java true
    maven-plugin jar = type java true
    ejb jar = type java true
    ejb-client client jar ejb java true
    war = type = type java true
    ear = type = type java true
    rar = type = type java true
    java-source sources jar = type java
    javadoc javadoc jar = type java true
  • scope:此元素指定該依賴項(xiàng)的作用范圍镊尺,以及如何限制該依賴項(xiàng)的可傳遞性朦佩。Maven 在編譯項(xiàng)目主代碼時(shí)需要使用一套 compile 的類路徑,Maven 在編譯和執(zhí)行測(cè)試的時(shí)候會(huì)使用一套 test 的類路徑庐氮。實(shí)際運(yùn)行 Maven 項(xiàng)目的時(shí)候语稠,又會(huì)使用 runtime 類路徑。有五個(gè)可用范圍:

    • compile這是默認(rèn)的范圍弄砍,在未指定任何范圍時(shí)使用仙畦。該作用范圍的依賴項(xiàng)在 compiletest音婶、runtime 等所有類路徑中都可用慨畸。
    • provided此范圍與 compile 范圍非常相似,但它表示依賴項(xiàng)僅在 compiletest 類路徑上可用衣式,在 runtime 類路徑不可用寸士。典型的就是 servlet-api 依賴項(xiàng),如果將該依賴項(xiàng)的 scope 設(shè)置為 provided碴卧,那么弱卡,該依賴在本地編譯和測(cè)試時(shí)可以使用該依賴項(xiàng),但運(yùn)行時(shí)會(huì)選擇使用 Tomcat 或 Jetty 等 Web 容器中的 servlet-api jar 包住册。
    • runtime:此范圍表示依賴項(xiàng)在 test婶博、runtime 類路徑下可用,但在 compile 類路徑時(shí)不可用荧飞。典型的就是 JDBC 驅(qū)動(dòng)實(shí)現(xiàn)凡人,項(xiàng)目主代碼編譯時(shí)只需要 JDK 提供的 JDBC 接口,只有在執(zhí)行測(cè)試或者運(yùn)行項(xiàng)目的才用到實(shí)現(xiàn) JDBC 接口的驅(qū)動(dòng)實(shí)現(xiàn)叹阔。
    • test:此范圍表示該依賴項(xiàng)僅在 test 類路徑下可用划栓。比如 Junit、TestNG条获、spring-boot-starter-test 等用作測(cè)試的依賴項(xiàng)僅在編譯測(cè)試代碼和運(yùn)行測(cè)試的時(shí)候才需要忠荞。
    • system:此范圍與 provided 的范圍一致。使用該范圍的依賴項(xiàng)必須配合 systemPath 元素一起使用。
  • systemPath:該元素值指定本地 jar 文件的路徑委煤。僅當(dāng) scope 元素值為 system 時(shí)才使用該元素拾因,否則衔肢,如果設(shè)置了該元素咒锻,則會(huì)導(dǎo)致構(gòu)建失敗比规。路徑必須是絕對(duì)路徑,因此建議使用 property 指定特定于計(jì)算機(jī)的路徑讥邻,例如 ${java.home}/lib迫靖。Maven 不會(huì)去倉(cāng)庫(kù)中檢查該依賴項(xiàng),而是會(huì)根據(jù)該元素值的路徑以確保文件存在兴使。如果不存在系宜,Maven 將使構(gòu)建失敗,并建議您手動(dòng)下載并安裝它发魄。

  • optional:當(dāng)此項(xiàng)目本身是依賴項(xiàng)時(shí)盹牧,將依賴項(xiàng)標(biāo)記為可選的。例如励幼,假設(shè)一個(gè)項(xiàng)目 A 依賴于項(xiàng)目 B 來編譯運(yùn)行時(shí)可能不使用的部分代碼汰寓,那么我們可能不需要對(duì)所有項(xiàng)目都使用項(xiàng)目 B。所以苹粟,如果項(xiàng)目 X 將項(xiàng)目 A 添加為它自己的依賴項(xiàng)有滑,那么,Maven 根本不需要安裝項(xiàng)目 B嵌削。假如用符號(hào)表示毛好,如果 if=> 表示一個(gè)必需的依賴項(xiàng),--> 表示可選的依賴項(xiàng)掷贾,盡管構(gòu)建項(xiàng)目 A 時(shí)的情況可能為 A=>B ,構(gòu)建項(xiàng)目 X 的情況則為 X=>A-->B荣茫。optional 范圍可以讓其他項(xiàng)目知道想帅,當(dāng)您使用該依賴時(shí),不一定非得需要該依賴項(xiàng)才能正常工作啡莉。

依賴解析規(guī)則

Maven 引人的傳遞性依賴機(jī)制港准,一方面大大簡(jiǎn)化和方便了依賴聲明,另一方面咧欣,大部分情況下我們只需要關(guān)心項(xiàng)目的直接依賴是什么浅缸,而不用考慮這些直接依賴會(huì)引入什么傳遞性依賴。但有時(shí)候魄咕,當(dāng)傳遞性依賴造成問題的時(shí)候衩椒,我們就需要清楚地知道該傳遞性依賴是從哪條依賴路徑引入的。

例如,項(xiàng)目 A 有這樣的依賴關(guān)系: A->B->C->X(1.0)毛萌,A->D->X(2.0)苟弛。X 是 A 的傳遞性依賴,但是兩條依賴路徑上有兩個(gè)版本的 X阁将,那么哪個(gè) X 會(huì)被 Maven 解析使用呢膏秫??jī)蓚€(gè)版本都被解析顯然是不對(duì)的,因?yàn)槟菚?huì)造成依賴重復(fù)做盅,因此必須選擇-一個(gè)缤削。Maven 依賴調(diào)解(Dependency Mediation)的第一原則是:路徑最近者優(yōu)先。該例中 X(1.0) 的路徑長(zhǎng)度為 3吹榴,而 X(2.0) 的路徑長(zhǎng)度為 2亭敢,因此 X(2.0) 會(huì)被解析使用。

依賴調(diào)解第一原則不能解決所有問題腊尚,比如這樣的依賴關(guān)系: A->B->Y(1.0)吨拗,A->C->Y(2.0), Y(1.0) 和 Y(2.0) 的依賴路徑長(zhǎng)度是一樣的婿斥,都為 2劝篷。那么到底誰(shuí)會(huì)被解析使用呢?在 Maven 2.0. 8 及之前的版本中民宿,這是不確定的娇妓,但是從 Maven2. 0.9 開始,為了盡可能避免構(gòu)建的不確定性活鹰,Maven 定義了依賴調(diào)解的第二原則:第一聲明者優(yōu)先哈恰。在依賴路徑長(zhǎng)度相等的前提下,在 POM 中依賴聲明的順序決定了誰(shuí)會(huì)被解析使用志群,順序最靠前的那個(gè)依賴優(yōu)勝着绷。該例中,如果 B 的依賴聲明在 C 之前锌云,那么 Y(1.0) 就會(huì)被解析使用荠医。

可以使用 maven-dependency-plugin 的一些目標(biāo)來輔助查看項(xiàng)目的依賴關(guān)系:

  • mvn dependency:list 命令列出已解析出的顯式聲明的依賴項(xiàng),不包括間接依賴項(xiàng)桑涎。
  • mvn dependency:tree 命令來列出實(shí)際生效的依賴項(xiàng)彬向。
  • mvn dependency:analyze 命令來分析此項(xiàng)目的依賴關(guān)系并確定哪些是已顯式聲明且已使用的依賴項(xiàng)、哪些是未顯式聲明但已使用的依賴項(xiàng)攻冷、哪些已顯式聲明但未使用的依賴項(xiàng)娃胆。

依賴版本規(guī)范

依賴項(xiàng)的 version 元素定義了版本需求,用來計(jì)算依賴項(xiàng)的版本等曼。軟需求(Soft Requirement)可以被依賴關(guān)系圖中同一工件的不同版本所替代里烦。硬需求(Hard Requirement)要求特定的一個(gè)或多個(gè)版本凿蒜,并覆蓋軟需求。如果不存在滿足當(dāng)前項(xiàng)目所有硬需求的依賴項(xiàng)版本招驴,則構(gòu)建失敗篙程。

版本需求具有以下語(yǔ)法:

  • 1.0:1.0 的軟需求。如果依賴關(guān)系樹中之前沒有出現(xiàn)其他版本别厘,則使用 1.0虱饿。
  • [1.0]:1.0 的硬需求。使用 1.0 且僅使用 1.0触趴。
  • (,1.0]:任何 <=1.0 的版本的硬需求氮发。
  • [1.2,1.3]:1.2 和 1.3 之間任何版本的硬需求(包含 1.2 和 1.3 版本)。
  • [1.0,2.0):1.0 <=x< 2.0冗懦,位于 1.0 版本(含)和 2.0 版本(不含)之間的任何版本的硬需求爽冕。
  • [1.5,):任何大于或等于 1.5 的版本的硬需求。
  • (,1.0],[1.2,):任何小于或等于 1.0披蕉,大于或等于 1.2颈畸,但不等于 1.1 的版本的硬需求。多個(gè)需求用逗號(hào)分隔没讲。
  • (,1.1),(1.1,):除 1.1 以外的任何版本的硬需求眯娱;例如,因?yàn)?1.1 有一個(gè)嚴(yán)重的漏洞爬凑。

Maven 選擇滿足當(dāng)前項(xiàng)目所有硬需求的最高版本的依賴項(xiàng)徙缴。如果沒有能夠滿足所有的硬需求的版本,那么構(gòu)建就會(huì)失敗嘁信。

版本順序規(guī)范

如果版本字符串在語(yǔ)法上是正確的語(yǔ)義化版本 1.0.0 規(guī)范 的版本號(hào)于样,那么在幾乎所有情況下,版本比較都遵循該規(guī)范中概述的優(yōu)先規(guī)則潘靖。這些版本是常見字母數(shù)字的 ASCII 字符串穿剖,如 2.15.2-alpha。更準(zhǔn)確地說卦溢,如果要比較的兩個(gè)版本號(hào)與語(yǔ)義版本控制規(guī)范中 BNF 語(yǔ)法中的 valid semver 產(chǎn)品相匹配糊余,則這是正確的。Maven 不考慮該規(guī)范所暗示的任何語(yǔ)義既绕。

重要提示:這僅適用于語(yǔ)義化版本 1.0.0 規(guī)范啄刹。Maven 版本順序算法與語(yǔ)義化版本 2.0.0 標(biāo)準(zhǔn)不兼容涮坐。特別是凄贩,Maven 對(duì)加號(hào)并不做特殊處理,也不考慮構(gòu)建標(biāo)識(shí)符袱讹。當(dāng)版本字符串不遵循語(yǔ)義化版本控制時(shí)疲扎,需要一組更復(fù)雜的規(guī)則昵时。Maven 使用點(diǎn)號(hào)(.)和連字符(-)之間標(biāo)記、數(shù)字與字母的轉(zhuǎn)換處來分割出坐標(biāo)椒丧。點(diǎn)號(hào)(.)和連字符(-)作為分隔符將被記錄壹甥,并將對(duì)順序產(chǎn)生影響。數(shù)字和字幕之間的轉(zhuǎn)換相當(dāng)于連字符壶熏、連續(xù)的分隔符之間的空標(biāo)記將替換為 0句柠。這將提供一系列帶有 .- 前綴的版本號(hào)(數(shù)字標(biāo)記)和版本限定符(非數(shù)字標(biāo)記)。分割和替換示例:1-1.foo-bar1baz-.1 -> 1-1.foo-bar-1-baz-0.1棒假。

然后溯职,從版本末尾開始,對(duì)尾部的 null 值(0, "", "final", "ga")將被切除帽哑。該處理在每個(gè)剩余的連字符處從頭到尾不斷重復(fù)谜酒。切除示例:

  • 1.0.0 -> 1
  • 1.ga -> 1
  • 1.final -> 1
  • 1.0 -> 1
  • 1. -> 1
  • 1- -> 1
  • 1.0.0-foo.0.0 -> 1-foo
  • 1.0.0-0.0.0 -> 1

版本順序是該前綴標(biāo)記序列的字典順序(lexicographical order),較短的一個(gè)標(biāo)記填充了足夠多的 null 值妻枕,并具有匹配的前綴僻族,與較長(zhǎng)的標(biāo)記具有相同的長(zhǎng)度。填充 null 值取決于另一版本的前綴:0 表示 .屡谐,而 - 表示 .述么。帶前綴的標(biāo)記順序?yàn)椋?/p>

  • 如果前綴相同,則比較標(biāo)記:

    • 數(shù)字標(biāo)記具有自然順序康嘉。

    • 非數(shù)字標(biāo)記(“限定符”)按字母順序排列碉输,但以下標(biāo)記按字母順序排在第一位:"alpha" < "beta" < "milestone" < "rc" = "cr" < "snapshot" < "" = "final" = "ga" < "sp"

      • "alpha"、"beta" 和 "milestone" 限定符在后面直接跟一個(gè)數(shù)字時(shí)亭珍,可以分別縮短為 a敷钾、bm
  • 或者:".qualifier" < "-qualifier" < "-number" < ".number"肄梨。

最終結(jié)果示例:

  • "1" < "1.1"(數(shù)字填充)
  • "1-snapshot" < "1" < "1-sp"(限定符填充)
  • "1-foo2" < "1-foo10"(正確地自動(dòng)“切換”到數(shù)字順序)
  • "1.foo" < "1-foo" < "1-1" < "1.1"
  • "1.ga" = "1-ga" = "1-0" = "1.0" = "1"(移除末尾的 null 值)
  • "1-sp" > "1-ga"
  • "1-sp.1" > "1-ga.1"
  • "1-sp-1" < "1-ga-1" = "1-1"(移除連字符處的 null 值)
  • "1-a1" = "1-alpha-1"

注意:與某些設(shè)計(jì)文檔中所述相反阻荒,對(duì)于版本順序,snapshot 的處理方式與 release 或任何其他限定符的處理方式?jīng)]有區(qū)別众羡。

版本順序測(cè)試

Maven 發(fā)行版包括一個(gè)比較指定版本之間順序的工具侨赡。有疑問時(shí),請(qǐng)自行運(yùn)行粱侣。您可以這樣運(yùn)行它:

java -jar ${MAVEN_HOME}/lib/maven-artifact-3.3.9.jar [versions...]

示例

$ java -jar ./lib/maven-artifact-3.3.9.jar  1 2 1.1
Display parameters as parsed by Maven (in canonical form) and comparison result:
1. 1 == 1
   1 < 2
2. 2 == 2
   2 > 1.1
3. 1.1 == 1.1

依賴排除

使用 exclusion 元素可以讓 Maven 在包含某個(gè)依賴項(xiàng)的時(shí)候不包含該依賴項(xiàng)的某些間接依賴項(xiàng)(換句話說羊壹,它的可傳遞依賴項(xiàng))。exclusions 元素可以包含一個(gè)或多個(gè) exclusion 元素齐婴,每個(gè)元素都包含一個(gè) groupId 和一個(gè) artifactId油猫,表示要排除的依賴項(xiàng)。與 optional(可能安裝和使用柠偶,也可能不安裝情妖、不使用)不同睬关,排除會(huì)主動(dòng)從依賴關(guān)系樹中刪除對(duì)應(yīng)的依賴項(xiàng)。例如毡证,maven-embedder 間接依賴于 maven-core电爹,我們不希望使用它或它的依賴項(xiàng),那么我們顯式地將 maven-core 的 groupId 和 artifact 放在 exclusion 元素中 料睛。

<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>

如果某個(gè)依賴項(xiàng)的作用域可能有無(wú)丐箩、當(dāng)前版本有安全漏洞、或與項(xiàng)目中的其他依賴項(xiàng)沖突恤煞,就有必要裁掉某個(gè)依賴項(xiàng)的可傳遞依賴項(xiàng)阱州。使用通配符排除可以輕松排除依賴項(xiàng)的所有可傳遞依賴項(xiàng)诈茧。在以下情況下,您可能正在使用 maven-embedder,并且您希望自己管理所使用的依賴項(xiàng)锤躁,因此您可以裁掉所有可傳遞的依賴項(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>

繼承

Maven 為構(gòu)建管理帶來的一個(gè)強(qiáng)大的補(bǔ)充是項(xiàng)目繼承的概念搁料。諸如 Ant 的構(gòu)建系統(tǒng)可以模擬繼承,但 Maven 在項(xiàng)目對(duì)象模型中已經(jī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">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>my-parent</artifactId>
  <version>2.0</version>
  <packaging>pom</packaging>
</project>

對(duì)于父項(xiàng)目來說郭计,其 pom.xml 中的 packaging 元素的值必須為 pom 類型。packaging 元素值會(huì)綁定到一組生命周期階段的目標(biāo)椒振。例如昭伸,如果打包是 jar,那么打包階段將執(zhí)行 jar:jar 目標(biāo)澎迎。父 POM 中的大多數(shù)元素都可以由其子 POM 繼承庐杨,包括:

  • groupId
  • version
  • description
  • url
  • inceptionYear
  • organization
  • licenses
  • developers
  • contributors
  • mailingLists
  • scm
  • issueManagement
  • ciManagement
  • properties
  • dependencyManagement
  • dependencies
  • repositories
  • pluginRepositories
  • build
    • plugin executions with matching ids
    • plugin configuration
    • etc.
  • reporting
  • profiles

未繼承的元素包括:

  • artifactId
  • name
  • prerequisites

子 POM 示例如下:

<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>
 
  <parent>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>my-parent</artifactId>
    <version>2.0</version>
    <relativePath>../my-parent</relativePath>
  </parent>
 
  <artifactId>my-project</artifactId>
</project>

請(qǐng)注意: relativePath 元素不是必需的,但可以作為 Maven 的一個(gè)標(biāo)志夹供,在搜索本地倉(cāng)庫(kù)和遠(yuǎn)程倉(cāng)庫(kù)之前灵份,先搜索 relativePath 元素值所指定的該項(xiàng)目的父項(xiàng)目的路徑。

Super POM

與面向?qū)ο缶幊讨袑?duì)象的繼承類似哮洽,擴(kuò)展父 POM 的 POM 從父 POM 繼承某些值填渠。此外,正如 Java 對(duì)象最終繼承自 java.lang.Object 一樣鸟辅,所有項(xiàng)目對(duì)象模型都繼承自一個(gè)基礎(chǔ)的 Super POM氛什。下面的代碼片段是 Maven 3.5.4 的 Super POM。

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <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>
 
  <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>
      <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>

通過創(chuàng)建一個(gè)最小的 pom.xml 并在命令行上執(zhí)行:mvn help:effective-pom匪凉,可以了解 Super POM 是如何影響項(xiàng)目對(duì)象模型的屉更。

依賴管理

除了繼承某些頂級(jí)元素外,父 POM 中的 <dependencyManagement> 元素可以幫助管理其所有子 POM 的依賴關(guān)系信息洒缀。父 POM 中 <dependencyManagement> 元素中所聲明的依賴項(xiàng)詳細(xì)信息會(huì)被子 POM 所繼承瑰谜,如果子 POM 在其 <dependecies> 元素中聲明了相同的依賴項(xiàng),則可以省略某些依賴項(xiàng)配置树绩,比如 version萨脑、scope。雖然父 POM 的 <dependencyManagement> 元素中設(shè)置了某個(gè)依賴項(xiàng)的詳細(xì)信息饺饭,但如果子 POM 中沒有使用對(duì)應(yīng)的 groupIdartifactId 來顯式使用該繼承的依賴項(xiàng)渤早,那么該子 POM 則不會(huì)使用該依賴項(xiàng)。當(dāng)然瘫俊,子 POM 也可以根據(jù)自己的實(shí)際情況來使用不同的依賴項(xiàng)配置來覆蓋所繼承的依賴項(xiàng)配置鹊杖。

比如悴灵,如果 my-parent 項(xiàng)目在其 dependencyManagement 元素中定義對(duì) junit:junit:4.12 的依賴關(guān)系,那么從這個(gè)項(xiàng)目繼承的子 POM 只需要提供 groupId=junitartifactId=junit 就可以使用父 POM 中聲明的這個(gè)依賴項(xiàng)骂蓖,Maven 將自動(dòng)填充父 POM 中所設(shè)置的 JUnit 依賴項(xiàng)版本积瞒。這種方法的好處是顯而易見的〉窍拢可以在一個(gè)中心位置配置依賴項(xiàng)的詳細(xì)信息茫孔,然后這些配置將傳播到所有子 POM。

聚合

通過 <modules> 元素來聲明多個(gè)模塊的項(xiàng)目稱為聚合項(xiàng)目(或多模塊項(xiàng)目)被芳,聚合項(xiàng)目的 <packaging> 元素值也必須為 pom缰贝。<modules> 元素的子元素<module> 指定某個(gè)子模塊相對(duì)于聚合項(xiàng)目的相對(duì)路徑。一般將聚合項(xiàng)目的子模塊項(xiàng)目放在聚合項(xiàng)目根目錄下作為子目錄存在畔濒,但不是絕對(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>
    <!-- 將聚合項(xiàng)目的子模塊項(xiàng)目放在聚合項(xiàng)目根目錄下作為子目錄存在 -->
    <module>my-project</module>
    <!-- 聚合項(xiàng)目的子模塊項(xiàng)目目錄與聚合項(xiàng)目目錄同級(jí) -->
    <module>../another-project</module>
  </modules>
</project>

在列出模塊時(shí),即使各子模塊之間有依賴關(guān)系侵状,也不需要考慮子模塊聲明順序李破。Maven 會(huì)對(duì)模塊進(jìn)行拓?fù)渑判颍@樣被依賴模塊總是在依賴模塊之前構(gòu)建壹将。但各模塊之間不能出現(xiàn)循環(huán)依賴嗤攻,否則,Maven 就會(huì)失敗诽俯。

繼承 VS 聚合

繼承和聚合通過單個(gè)高級(jí) POM 創(chuàng)建一個(gè)很好的動(dòng)態(tài)來控制構(gòu)建妇菱。父項(xiàng)目和聚合項(xiàng)目的 <packaging> 元素值都是 pom,兩者除了 POM 以外均不含其他內(nèi)容暴区。經(jīng)常會(huì)看到一個(gè)項(xiàng)目既是父項(xiàng)目又是聚合項(xiàng)目闯团,但繼承和聚合不是一個(gè)概念。兩者不同之處如下:

  • 父項(xiàng)目的主要目的是為了消除重復(fù)配置仙粱。父項(xiàng)目的 pom.xml 中可以不含模塊而單單作為一個(gè)父項(xiàng)目來被其子項(xiàng)目通過 <parent> 元素來繼承竣蹦,此時(shí)产徊,父項(xiàng)目?jī)H僅是父項(xiàng)目,而不是一個(gè)聚合項(xiàng)目。父項(xiàng)目不知道哪些子項(xiàng)目繼承了它嚣潜,而子項(xiàng)目知道它繼承了哪個(gè)父項(xiàng)目更舞。
  • 聚合項(xiàng)目的目的是便于管理多個(gè)模塊掠剑。聚合項(xiàng)目的 pom.xml 中可通過包含若干個(gè)子模塊竟痰,從而將這些子模塊歸為一個(gè)組來統(tǒng)一管理這些子模塊,比如硬霍,統(tǒng)一 clean帜慢、compile 所有子模塊。而子模塊不需要特殊的聲明。聚合項(xiàng)目知道自己聚合了哪些模塊粱玲,但子模塊不知道誰(shuí)聚合了自己以及和誰(shuí)一起被聚合躬柬。

property

Maven 的 property 是值占位符,就像 Ant 中的 property 一樣抽减。它們的值可以通過使用符號(hào) ${X} 在 POM 中的任何位置訪問允青,其中 X 是 property】杷Γ或者它們可以被插件用作默認(rèn)值,例如:

<project>
  ...
  <properties>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <!-- Following project.-properties are reserved for Maven in will become elements in a future POM definition. -->
    <!-- Don't start your own properties properties with project. -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  </properties>
  ...
</project>

Property 有五種不同的風(fēng)格:

  • env.X:在變量前面加上 env. 將返回 shell 的環(huán)境變量堪嫂。例如偎箫,${env.PATH} 包含 PATH 環(huán)境變量。雖然環(huán)境變量本身在 Windows 上不區(qū)分大小寫皆串,但 property 的查找是區(qū)分大小寫的淹办。換句話說,雖然 Windows shell 為 %PATH%%Path% 返回相同的值恶复,但 Maven 區(qū)分了 ${env.PATH}${env.Path}怜森。為了可靠性起見,環(huán)境變量的名稱被規(guī)范化為所有大寫谤牡。
  • project.x:POM 中以點(diǎn)號(hào)(.)表示的路徑將包含相應(yīng)元素的值副硅。例如:<project><version>1.0</version></project> 可以通過 ${project.version} 來訪問。
  • settings.xsettings.xml 中以點(diǎn)號(hào)(.)表示的路徑將包含相應(yīng)元素的值翅萤。例如:<settings><offline>false</offline></settings> 可通過${settings.offline} 訪問恐疲。
  • Java 系統(tǒng)屬性:通過 java.lang.System.getProperties() 訪問的所有屬性都可以作為 POM property 使用,例如 ${java.home}套么。
  • x:在 POM 中的 <properties/> 元素內(nèi)設(shè)置培己。<properties><someVar>value</someVar></properties> 的值可以用作 ${someVar}

Build Setting

構(gòu)建

根據(jù) POM 4.0.0 XSD胚泌,<build> 元素在概念上分為兩部分省咨,對(duì)應(yīng)一個(gè) BaseBuild 類型,它包含兩個(gè) <build> 元素共有的元素集:<project> 元素下和 <profiles> 元素下的頂級(jí) <build> 元素玷室;還有一個(gè) Build 類型零蓉,它包含 BaseBuild 集合以及頂層定義的更多元素。讓我們從分析兩者之間的共同點(diǎn)開始穷缤。注意:這些不同的 <build> 元素可以表示為 project buildprofile build壁公。

<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">
  ...
  <!-- "Project Build" contains more elements than just the BaseBuild set -->
  <build>...</build>
 
  <profiles>
    <profile>
      <!-- "Profile Build" contains a subset of "Project Build"s elements -->
      <build>...</build>
    </profile>
  </profiles>
</project>

基礎(chǔ)構(gòu)建元素

BaseBuild 類型就像聽起來的那樣,POM 中兩個(gè) <build> 元素中的定級(jí)子元素元素的集合绅项。

<build>
  <defaultGoal>install</defaultGoal>
  <directory>${basedir}/target</directory>
  <finalName>${artifactId}-${version}</finalName>
  <filters>
    <filter>filters/filter1.properties</filter>
  </filters>
  ...
</build>
  • defaultGoal:當(dāng)沒有給定目標(biāo)或階段時(shí)所要執(zhí)行的默認(rèn)目標(biāo)或階段紊册。如果給定了一個(gè)目標(biāo),那么應(yīng)該在命令行中定義它(例如 jar:jar)。如果定義了一個(gè)階段(如 install)囊陡,則情況也是如此芳绩。
  • directory:構(gòu)建輸出的目標(biāo)目錄。它默認(rèn)為 ${basedir}/target撞反。
  • finalName:這是最終構(gòu)建項(xiàng)目時(shí)的項(xiàng)目名稱(無(wú)文件擴(kuò)展名妥色,例如:my-project-1.0.jar)。它默認(rèn)為 ${artifactId}-${version}遏片。然而嘹害,finalName 的術(shù)語(yǔ)有點(diǎn)用詞不當(dāng),因?yàn)闃?gòu)建項(xiàng)目的插件完全有權(quán)忽略/修改這個(gè)名稱(但通常不會(huì))吮便。例如笔呀,如果 maven-jar-plugin 插件被配置為給 jar 一個(gè) testclassifier,那么上面定義的實(shí)際 jar 將被構(gòu)建為 my-project-1.0-test.jar髓需。
  • filter:指定一個(gè) *.properties 文件许师,該文件中定義的 name=value 對(duì)在構(gòu)建時(shí)將用于替換資源中的 ${name} 字符串。上面的示例在 filters/ 目錄下定義了 filter1.properties 文件僚匆。Maven 的默認(rèn)過濾器目錄是 ${basedir}/src/main/filters/微渠。

資源

<build> 元素的另一個(gè)特性是指定資源在項(xiàng)目中的位置。資源通常不是代碼咧擂,它們不會(huì)編譯逞盆,而是要捆綁在項(xiàng)目中或用于各種其他用途(如代碼生成、用作項(xiàng)目的配置文件)松申。例如纳击,Plexus 項(xiàng)目需要在 META-INF/plexus 目錄中存放一個(gè) configuration.xml 文件(指定容器的組件配置)。盡管我們可以同樣輕松地將此文件放在 src/main/resources/META-INF/plexus 中攻臀,但我們希望將它自己的目錄 src/main/plexus 提供給 Plexus焕数。為了讓 JAR 插件正確綁定資源,您可以指定類似以下內(nèi)容的資源:

<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">
  <build>
    ...
    <resources>
        <!-- 指定模塊中所用資源所在的目錄 -->
        <resource>
            <!-- 默認(rèn)資源目錄為src/main/resources -->
            <directory>src/main/resources</directory>
            <!-- filtering設(shè)置為true會(huì)將文本類型的資源文件中使用${name}表示的屬性值替換為對(duì)應(yīng)屬性值(這些屬性可以有五種聲明方式刨啸,
            參考關(guān)于Property的說明 -->
            <filtering>true</filtering>
            <!-- 指定需要輸出的資源文件(文本文件可以使用屬性引用的替換) -->
            <!-- 不輸出src/main/resources目錄下的所有.properties和.xml資源文件 -->
            <includes>
                <include>**/*.properties</include> <!-- 輸出src/main/resources目錄下的所有txt資源文件 -->
                <include>**/*.xml</include> <!-- 輸出src/main/resources目錄下的所有xml資源文件 -->
            </includes>
            <!-- 指定不需要輸出資源文件(二進(jìn)制文件不能使用屬性引用的替換堡赔,否則可能會(huì)損壞二進(jìn)制文件) -->
            <!-- 不輸出src/main/resources目錄下的所有.bmp和.jpg資源文件 -->
            <excludes>
                <exclude>**/*.bmp</exclude> 
                <exclude>**/*.jpg</exclude>
            </excludes>
        </resource>
        <!-- 可以使用多個(gè)resource元素來指定多個(gè)資源目錄 -->
        <resource>
            <directory>src/main/resources-filtered</directory>
            <!-- includes和excludes可以組合使用。如下配置會(huì)輸出資源目錄下的所有txt文件但除了名稱中包含test的txt文件以外 -->
            <includes>
                <include>**/*.txt</include>
            </includes>
            <excludes>
                <exclude>**/*test*.*</exclude>
            </excludes>
        </resource>
    </resources>
    <testResources>
        <testResource>
            <!-- ... -->
        </testResource>
    </testResources>
    ...
  </build>
</project>
  • <resources>:是 <resource> 元素的列表设联,每個(gè) <resource> 元素用于選擇將哪些資源文件復(fù)制到構(gòu)建輸出的類路徑下善已,執(zhí)行復(fù)制操作之前還可能對(duì)文本類資源文件中的 property 引用進(jìn)行替換。
  • <targetPath>:資源經(jīng)構(gòu)建之后的存放目錄离例。目標(biāo)路徑默認(rèn)為基本目錄换团。一般會(huì)把 META-INF 目標(biāo)目錄會(huì)打包到 JAR 包中。
  • <filtering>:為 truefalse宫蛆,表示是否要替換資源文件中的某些 property 引用艘包。請(qǐng)注意,如果要替換 property 的引用,不一定非要在 <filters> 定義 *.properties 文件想虎,資源還可以使用 POM 中默認(rèn)定義的 property (例如 ${project.version})卦尊、 傳遞到命令行的 -D 選項(xiàng)參數(shù)(例如,-Dname=value)或由 <properties> 元素顯式定義的 property舌厨。
  • <directory>:這個(gè)元素的值定義了在哪里可以找到資源岂却,默認(rèn)為 ${basedir}/src/main/resources
  • <includes>:一組文件模式裙椭,使用 * 作為通配符躏哩,指定 <directory> 元素值所指定目錄下的哪些文件和目錄要包含在 <targetPath> 目錄下。
  • <excludes>:與 <includes> 元素結(jié)構(gòu)相同揉燃,但指定要排除的文件扫尺。如果一個(gè)路徑同時(shí)匹配 <includes><excludes> 中的模式,則忽略匹配的包含模式而排除處理你雌。
  • <testResources><testResources> 元素包含 <testResource> 元素器联。它們的定義類似于資源元素二汛,但在測(cè)試階段自然使用婿崭。一個(gè)區(qū)別是項(xiàng)目的默認(rèn)(超級(jí) POM 定義的)測(cè)試資源目錄是 ${basedir}/src/test/resources。未部署測(cè)試資源肴颊。

再看下面一個(gè) Spring Boot 項(xiàng)目管理不同運(yùn)行環(huá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">
  <build>
    ...
    <!-- 聲明了三個(gè)運(yùn)行環(huán)境的 profile:開發(fā)氓栈、測(cè)試、UAT婿着、生產(chǎn)授瘦。當(dāng)通過id激活了某個(gè) profile 之后,對(duì)應(yīng)的activeProfile屬性就會(huì)起作用 -->
    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <activeProfile>dev-res</activeProfile>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>

        <profile>
            <id>test</id>
            <properties>
                <activeProfile>test-res</activeProfile>
            </properties>
        </profile>
        <profile>
            <id>uat</id>
            <properties>
                <activeProfile>uat-res</activeProfile>
            </properties>
        </profile>
        <profile>
            <id>pro</id>
            <properties>
                <activeProfile>pro-res</activeProfile>
            </properties>
        </profile>
    </profiles>
    ...
    <resources>
        <resource>
            <!-- 默認(rèn)資源目錄為src/main/resources竟宋。建議將不同環(huán)境下同名的資源文件分開存放 -->
            <!-- 假如src/main/resources存在以下子路徑:env/dev-res/提完、env/test-res/、env/uat-res/丘侠、env/pro-res/徒欣,
            每個(gè)子路徑下存放了一些對(duì)應(yīng)運(yùn)行環(huán)境的資源文件 -->
            <directory>src/main/resources</directory>
            <!-- 排除env子目錄下的所有資源文件 -->
            <excludes>
                <exclude>env/**</exclude>
            </excludes>
        </resource>
        <!-- 使用另一個(gè)resource元素來包含某個(gè)激活的 profile 中 activeProfile 屬性值所構(gòu)成的資源路徑 -->
        <!-- src/main/resources/env/${activeProfile} 路徑下的資源文件將直接復(fù)制到構(gòu)建輸出目錄的類路徑下 -->
        <resource>
            <directory>src/main/resources/env/${activeProfile}</directory>
            <includes>
                <include>**</include>
            </includes>
        </resource>
    </resources>
    ...
  </build>
</project>

在上面的例子中,通過激活某個(gè) profile 可以選擇將 src/main/resources/env/${activeProfile} 路徑下的資源文件復(fù)制到構(gòu)建輸出的類路徑下蜗字,就不用來回復(fù)制替換不同運(yùn)行環(huán)境下的資源文件了打肝。如果你使用 Intellig IDEA 進(jìn)行開發(fā),可以直接在 Maven 插件提供的 Profile 復(fù)選框勾選來激活對(duì)應(yīng)的 profile挪捕,非常方便粗梭。也可以通過命令行參數(shù)來激活某個(gè) profile。

插件

<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">
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.6</version>
        <extensions>false</extensions>
        <inherited>true</inherited>
        <configuration>
          <classifier>test</classifier>
        </configuration>
        <dependencies>...</dependencies>
        <executions>...</executions>
      </plugin>
    </plugins>
  </build>
</project>

除了 groupId:artifactId:version 的標(biāo)準(zhǔn)坐標(biāo)之外级零,還有一些用于配置插件或與構(gòu)建進(jìn)行交互的元素断医。

  • extensionstruefalse,是否加載此插件的擴(kuò)展。它默認(rèn)為 false孩锡。

  • inheritedtruefalse酷宵,該插件配置是否應(yīng)用于從該 POM 繼承的子 POM。默認(rèn)值為 true躬窜。

  • configuration:這是特定于單個(gè)插件的浇垦。在不深入討論插件如何工作的機(jī)制的情況下,只需說明插件 Mojo 可能期望的任何屬性(javamojobean中的getter和setter)都可以在這里指定荣挨。在上面的示例中男韧,我們將在 maven-jar-plugin 的 Mojo 中設(shè)置 classifiertest。值得注意的是默垄,所有配置元素此虑,無(wú)論它們位于 POM 中的何處,都旨在將值傳遞給另一個(gè)底層系統(tǒng)口锭,例如插件朦前。換句話說:POM 語(yǔ)法從未顯式聲明需要 configuration 元素中的值,但插件目標(biāo)完全有權(quán)要求必需提供 configuration 元素中的值鹃操。

    如果您的 POM 繼承自一個(gè)父 POM韭寸,它將從父級(jí)的 <build>/<plugins> 元素和 <pluginManagement> 元素中繼承插件配置。

    默認(rèn)配置繼承

    為了說明荆隘,請(qǐng)看來自某個(gè)父 POM 的以下片段:

    <plugin>
      <groupId>my.group</groupId>
      <artifactId>my-plugin</artifactId>
      <configuration>
        <items>
          <item>parent-1</item>
          <item>parent-2</item>
        </items>
        <properties>
          <parentKey>parent</parentKey>
        </properties>
      </configuration>
    </plugin>
    

    下面的 POM 片段所在的項(xiàng)目繼承了上面 POM 片段所在的項(xiàng)目:

    <plugin>
      <groupId>my.group</groupId>
      <artifactId>my-plugin</artifactId>
      <configuration>
        <items>
          <item>child-1</item>
        </items>
        <properties>
          <childKey>child</childKey>
        </properties>
      </configuration>
    </plugin>
    

    默認(rèn)行為是根據(jù)元素名稱合并配置元素的內(nèi)容恩伺。如果子 POM 具有父 POM 所沒有的元素,或子 POM 具有和父 POM 相同的元素椰拒,則子 POM 中的該元素將成為有效值晶渠。如果父 POM 具有子 POM 所有沒有的元素,則父 POM 中的該元素將成為有效值燃观。這純粹是對(duì) XML 的操作褒脯,不涉及插件本身的代碼或配置。只涉及元素缆毁,而不涉及它們的值番川。

    將這些規(guī)則應(yīng)用到示例中,子 POM 中實(shí)際生效的結(jié)果如下:

    <plugin>
      <groupId>my.group</groupId>
      <artifactId>my-plugin</artifactId>
      <configuration>
        <items>
          <item>child-1</item>
        </items>
        <properties>
          <childKey>child</childKey>
          <parentKey>parent</parentKey>
        </properties>
      </configuration>
    </plugin>
    

    高級(jí)配置集成

    通過向 <configuration> 元素的子元素添加屬性积锅,可以控制子 POM 如何從父 POM 繼承配置爽彤。屬性為 combine.childrencombine.self。在子 POM 中使用這些屬性來控制 Maven 如何將父級(jí)的插件配置與子級(jí)的顯式配置相結(jié)合缚陷。

    以下是子配置中的兩個(gè)屬性的示例:

    <configuration>
      <items combine.children="append">
        <!-- combine.children="merge" is the default -->
        <item>child-1</item>
      </items>
      <properties combine.self="override">
        <!-- combine.self="merge" is the default -->
        <childKey>child</childKey>
      </properties>
    </configuration>
    

    那么适篙,有效配置如下:

    <configuration>
      <items combine.children="append">
        <item>parent-1</item>
        <item>parent-2</item>
        <item>child-1</item>
      </items>
      <properties combine.self="override">
        <childKey>child</childKey>
      </properties>
    </configuration>
    

    combine.children=“append” 將按順序連接父元素和子元素中的值。另一方面箫爷,combine.self=“override” 完全覆蓋對(duì)應(yīng)的父配置嚷节。如果嘗試對(duì)一個(gè)元素同時(shí)使用 combine.self=“override”combine.children=“append”聂儒,則 override 將占據(jù)上風(fēng)

    請(qǐng)注意硫痰,這些 attribute 僅應(yīng)用于聲明它們的配置元素衩婚,而不會(huì)傳播到下一級(jí)的嵌套子元素。也就是說效斑,如果來自子 POM 的 <item> 元素的內(nèi)容是一個(gè)復(fù)雜的結(jié)構(gòu)而不是文本非春,那么它的子元素仍將遵循默認(rèn)的合并策略,除非這些子元素使用了 combine.* attribute缓屠。combine.* attribute 從父 POM 繼承到子 POM奇昙。將這些 attribute 添加到父 POM 時(shí)要小心,因?yàn)檫@可能會(huì)影響其子 POM 或其孫子 POM敌完。

  • dependencies:在 POM 中的許多位置都可以看到 <dependencies> 元素储耐,當(dāng)該元素可以出現(xiàn)在 <plugin> 元素中時(shí), 其的結(jié)構(gòu)和功能與在基礎(chǔ)構(gòu)建下時(shí)相同滨溉。不同的是什湘,<plugin> 元素下的 <dependencies> 元素不再作為項(xiàng)目的依賴項(xiàng),而是作為它們所處插件的依賴項(xiàng)晦攒。它的功能是改變插件的依賴項(xiàng)列表闽撤,可能是通過排除刪除未使用的運(yùn)行時(shí)依賴項(xiàng),或者改變所需依賴項(xiàng)的版本勤家。

  • executions:一個(gè)插件可能有多個(gè)目標(biāo)腹尖。每個(gè)目標(biāo)可能有一個(gè)單獨(dú)的配置柳恐,甚至可能將插件的目標(biāo)綁定到一個(gè)不同的階段伐脖。<executions> 配置一個(gè)插件目標(biāo)的 <execution>。例如乐设,假設(shè)您想要將 antrun:run 目標(biāo)綁定到 verify 階段讼庇。我們希望任務(wù)回顯構(gòu)建目錄,并通過將 inherited 設(shè)置為 false 避免將此配置傳遞給其子級(jí)(假設(shè)它是父級(jí))近尚。您將得到如下 <execution>

    <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">
      ...
      <build>
        <plugins>
          <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.1</version>
            <executions>
              <execution>
                <id>echodir</id>
                <goals>
                  <goal>run</goal>
                </goals>
                <phase>verify</phase>
                <inherited>false</inherited>
                <configuration>
                  <tasks>
                    <echo>Build Dir: ${project.build.directory}</echo>
                  </tasks>
                </configuration>
              </execution>
            </executions>
     
          </plugin>
        </plugins>
      </build>
    </project>
    
    • id:不言自明蠕啄,用于在所有執(zhí)行塊中標(biāo)識(shí)該執(zhí)行塊。當(dāng)階段運(yùn)行時(shí)戈锻,它將以以下形式顯示:[plugin:goal execution: id]歼跟。在本例中:[antrun:run execution: echodir]
    • goals:與所有復(fù)數(shù)名稱的 POM 元素一樣格遭,它是一個(gè) <goal> 元素的列表哈街。
    • phase:這是 <goals> 列表執(zhí)行時(shí)所處的階段。這是一個(gè)非常強(qiáng)大的選項(xiàng)拒迅,允許將任何目標(biāo)綁定到構(gòu)建生命周期的任何階段骚秦,從而改變 Maven 的默認(rèn)行為她倘。
    • inherited:與上面的 <inherited> 元素一樣,將此設(shè)置為 false 將禁止 Maven 將此執(zhí)行傳遞給其子級(jí)作箍。此元素僅對(duì)父 POM 有意義硬梁。
    • configuration:與上面相同,但是將配置限制在這個(gè)特定的目標(biāo)列表中胞得,而不是插件下的所有目標(biāo)荧止。

插件管理

<pluginManagement> 是一個(gè)與 <plugins> 同級(jí)的元素,用于管理插件阶剑。<pluginManagement> 元素包含插件元素的方式與 <plugins> 元素基本相同罩息,不同之處在于,這里的定義僅僅是為子項(xiàng)目或當(dāng)前項(xiàng)目的 <plugins> 元素中實(shí)際引用的插件提供一些默認(rèn)配置个扰,如果子項(xiàng)目或當(dāng)前項(xiàng)目的 <plugins> 元素中沒有使用 <pluginManagement> 元素中的某些插件聲明瓷炮,則子項(xiàng)目或當(dāng)前項(xiàng)目就不會(huì)使用對(duì)應(yīng)插件。子項(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">
  ...
  <build>
    ...
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <version>2.6</version>
          <executions>
            <execution>
              <id>pre-process-classes</id>
              <phase>compile</phase>
              <goals>
                <goal>jar</goal>
              </goals>
              <configuration>
                <classifier>pre-process</classifier>
              </configuration>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
    ...
  </build>
</project>

如果某個(gè)子 POM 通過以下片段繼承了上面的 POM娘香,或者當(dāng)前 POM 在包含上面 <pluginManagement> 元素聲明的同時(shí),還聲明了在當(dāng)前 POM 中聲明了以下片段的配置办龄,則就可以完全按照 <pluginManagement> 元素所聲明的那樣來使用對(duì)應(yīng)的插件烘绽,而不需要完全照抄一份,因?yàn)橐呀?jīng)從 <pluginManagement> 元素繼承了一些默認(rè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">
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
      </plugin>
    </plugins>
    ...
  </build>
</project>

<build> 中的其他元素

XSD 中的 Build 類型表示那些僅可用于項(xiàng)目構(gòu)建的元素安接。盡管有很多額外的元素,但 <project>/<build> 中實(shí)際上只包含兩組 <profile>/<build> 中所缺少的元素:目錄和擴(kuò)展英融。

目錄

目錄元素集位于父 <build> 元素中盏檐,父 <build> 元素將 POM 作為一個(gè)整體設(shè)置各種目錄結(jié)構(gòu)。因?yàn)樗鼈儾淮嬖谟?<profile>/<build> 中驶悟,所以 <profile> 不能修改它們胡野。

<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">
  ...
  <build>
    <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
    <scriptSourceDirectory>${basedir}/src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
    <outputDirectory>${basedir}/target/classes</outputDirectory>
    <testOutputDirectory>${basedir}/target/test-classes</testOutputDirectory>
    ...
  </build>
</project>

如果上面的 <*Directory> 元素的值設(shè)置為絕對(duì)路徑(當(dāng)其 property 替換成實(shí)際值時(shí)),則使用該絕對(duì)路徑痕鳍。否則硫豆,則使用相對(duì)于 ${basedir} 目錄的相對(duì)路徑。請(qǐng)注意笼呆,scriptSourceDirectory 在 Maven 中沒有使用熊响,已經(jīng)過時(shí)。

擴(kuò)展

擴(kuò)展(通過 <extensions> 元素)是要在此構(gòu)建中使用的工件的列表诗赌,這些工件將包含在正在運(yùn)行的構(gòu)建的類路徑中汗茄,這些工件可以支持對(duì)構(gòu)建過程的擴(kuò)展,以及激活插件從而更改構(gòu)建生命周期境肾。簡(jiǎn)而言之剔难,擴(kuò)展是在構(gòu)建期間激活的工件胆屿。擴(kuò)展不必實(shí)際執(zhí)行任何操作,也不必包含 Mojo偶宫。因此非迹,擴(kuò)展非常適合指定公共插件接口的多個(gè)實(shí)現(xiàn)中的一個(gè)。

<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">
  ...
  <build>
    ...
    <extensions>
      <extension>
        <groupId>org.apache.maven.wagon</groupId>
        <artifactId>wagon-ftp</artifactId>
        <version>1.0-alpha-3</version>
      </extension>
    </extensions>
    ...
  </build>
</project>

reporting

<reporting> 元素包含與站點(diǎn)生成階段相關(guān)的元素纯趋。某些 Maven 插件可以生成在 <reporting> 元素下定義和配置的報(bào)告憎兽,例如:生成 Javadoc 報(bào)告。與 <build> 元素配置插件的功能非常相似吵冒,<reporting> 元素具有相同的功能纯命。明顯的區(qū)別在于, <reporting> 元素在 <reportSet> 元素中配置目標(biāo)痹栖,而不是在 <executions> 元素中對(duì)插件目標(biāo)進(jìn)行細(xì)粒度控制祈远。更微妙的區(qū)別是然眼, <reporting> 元素下插件的 <configuration> 可以用作 <build> 中插件的 <configuration>躺涝,盡管相反的情況并非如此: <build> 中插件 <configuration> 不會(huì)影響 <reporting> 中的插件仔夺。

了解 <build> 元素的人對(duì)于 <reporting> 元素可能唯一不熟悉的是 Boolean 類型的 <excludeDefaults> 元素。此元素指示站點(diǎn)生成器排除默認(rèn)情況下通常生成的報(bào)告南捂。通過 site 構(gòu)建周期生成站點(diǎn)時(shí)吴裤,左側(cè)菜單中會(huì)顯示一個(gè) Project Info 部分,其中包含大量報(bào)告溺健,例如 Project Team 報(bào)告或 Dependencies 列表報(bào)告麦牺。這些報(bào)告目標(biāo)由 maven-project-info-reports-plugin 插件生成的。與其他插件一樣鞭缭,它也可能以下更詳細(xì)的方式被抑制剖膳,從而有效地關(guān)閉項(xiàng)目信息報(bào)告。

<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">
  ...
  <reporting>
    <outputDirectory>${basedir}/target/site</outputDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-project-info-reports-plugin</artifactId>
        <version>2.0.1</version>
        <reportSets>
          <reportSet></reportSet>
        </reportSets>
      </plugin>
    </plugins>
  </reporting>
  ...
</project>

另一個(gè)區(qū)別是 <plugin> 下的 <outputDirectory> 元素缚去。在 <reporting> 下潮秘,輸出目錄默認(rèn)為 ${basedir}/target/site琼开。

重要的是要記住易结,一個(gè)插件可能有多個(gè)目標(biāo)。每個(gè)目標(biāo)可能有一個(gè)單獨(dú)的配置柜候。<reportSets> 配置報(bào)告類插件的目標(biāo)的執(zhí)行搞动,這聽起來熟悉吧?關(guān)于構(gòu)建的 <execution> 元素也說了同樣的話渣刷,但有一個(gè)區(qū)別:不能將報(bào)告類插件的目標(biāo)綁定到另一個(gè)階段鹦肿。

例如,假設(shè)我們想要配置要鏈接到 http://java.sun.com/j2se/1.5.0/docs/api/javadoc:javadoc 目標(biāo)辅柴,但只有 javadoc 目標(biāo)(而不是 maven-javadoc-plugin:jar)箩溃。我們還希望將此配置傳遞給其子級(jí)瞭吃,并將 <inherited> 設(shè)置為 true。 <reportSets> 類似于以下內(nèi)容:

<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">
  ...
  <reporting>
    <plugins>
      <plugin>
        ...
        <reportSets>
          <reportSet>
            <id>sunlink</id>
            <reports>
              <report>javadoc</report>
            </reports>
            <inherited>true</inherited>
            <configuration>
              <links>
                <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
              </links>
            </configuration>
          </reportSet>
        </reportSets>
      </plugin>
    </plugins>
  </reporting>
  ...
</project>

<build><executions><reporting><reportSets> 之間涣旨,現(xiàn)在應(yīng)該清楚它們存在的原因歪架。POM 不僅必須有一種方法來配置插件,還必須配置這些插件的目標(biāo)霹陡。這就是這些元素的用武之地和蚪,使 POM 以最細(xì)的粒度來控制其構(gòu)建行為。

更多項(xiàng)目信息

有幾個(gè)元素不影響構(gòu)建烹棉,而是記錄項(xiàng)目以方便開發(fā)人員攒霹。在生成項(xiàng)目網(wǎng)站時(shí),這些元素中的許多元素用于填充項(xiàng)目詳細(xì)信息浆洗。然而催束,像所有POM聲明一樣,插件可以將它們用于任何事情伏社。以下是最簡(jiǎn)單的元素:

  • name:除了 artifactId 之外泣崩,項(xiàng)目往往有非正式的名字。Sun 的工程師們并沒有將他們的項(xiàng)目稱為 java-1.5洛口,而只是稱之為 Tiger矫付。這里是設(shè)置該值的位置。
  • description:項(xiàng)目的簡(jiǎn)短易讀描述第焰。盡管這不應(yīng)取代正式的文檔买优,但對(duì) POM 的任何讀者的快速評(píng)論總是有幫助的。
  • url:項(xiàng)目的主頁(yè)挺举。
  • inceptionYear:項(xiàng)目最初創(chuàng)建的年份杀赢。

licenses

<licenses>
  <license>
    <name>Apache License, Version 2.0</name>
    <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
    <distribution>repo</distribution>
    <comments>A business-friendly OSS license</comments>
  </license>
</licenses>

<licenses> 是定義如何以及何時(shí)使用項(xiàng)目(或項(xiàng)目的一部分)的法律文件。項(xiàng)目應(yīng)該列出直接應(yīng)用于此項(xiàng)目的許可證湘纵,而不是列出應(yīng)用于項(xiàng)目依賴項(xiàng)的許可證脂崔。

  • nameurlcomments:是不言自明的梧喷,以前在其他上下文中也遇到過砌左。建議使用 SPDX 標(biāo)識(shí)符作為許可證名稱。第四個(gè)許可要素是:
  • distribution:描述如何合法發(fā)布項(xiàng)目铺敌。這兩種方法: repo(可以從 Maven 存儲(chǔ)庫(kù)下載)或 manual(必須手動(dòng)安裝)汇歹。

organization

大多數(shù)項(xiàng)目由某種組織(企業(yè)、私人團(tuán)體等)運(yùn)行偿凭。這里是設(shè)置最基本信息的地方产弹。

<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">
  ...
  <organization>
    <name>Codehaus Mojo</name>
    <url>http://mojo.codehaus.org</url>
  </organization>
</project>

developers

所有項(xiàng)目都由一個(gè)人在某個(gè)時(shí)間創(chuàng)建的文件組成。與圍繞項(xiàng)目的其他系統(tǒng)一樣弯囊,參與項(xiàng)目的人員也與項(xiàng)目有利害關(guān)系痰哨。開發(fā)人員可能是項(xiàng)目核心開發(fā)的成員胶果。請(qǐng)注意,盡管一個(gè)組織可能有許多開發(fā)人員(程序員)作為成員斤斧,但將他們?nèi)苛袨殚_發(fā)人員并不是一種好的形式稽物,而只列出那些直接負(fù)責(zé)代碼的人。一個(gè)很好的經(jīng)驗(yàn)法則是折欠,如果不應(yīng)該因?yàn)轫?xiàng)目聯(liá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">
  ...
  <developers>
    <developer>
      <id>jdoe</id>
      <name>John Doe</name>
      <email>jdoe@example.com</email>
      <url>http://www.example.com/jdoe</url>
      <organization>ACME</organization>
      <organizationUrl>http://www.example.com</organizationUrl>
      <roles>
        <role>architect</role>
        <role>developer</role>
      </roles>
      <timezone>America/New_York</timezone>
      <properties>
        <picUrl>http://www.example.com/jdoe/pic</picUrl>
      </properties>
    </developer>
  </developers>
  ...
</project>
  • id锐秦、name咪奖、email:這些對(duì)應(yīng)于開發(fā)人員的 id(可能是整個(gè)組織中的某個(gè)唯一 id)、開發(fā)人員的姓名和電子郵件地址酱床。
  • organization羊赵、organizationUrl:正如您可能猜到的,這是開發(fā)人員的組織名稱和 URL扇谣。
  • roles:角色應(yīng)指定該人員負(fù)責(zé)的標(biāo)準(zhǔn)操作昧捷。就像一個(gè)人可以戴很多帽子一樣,一個(gè)人可以扮演多個(gè)角色罐寨。
  • timezone:一個(gè)有效的時(shí)區(qū) ID靡挥,如 America/New_YorkEurope/Berlin,或以小時(shí)(和分?jǐn)?shù))為單位的數(shù)字偏移量(基于開發(fā)人員居住的 UTC 時(shí)間)例如 -5+1鸯绿。時(shí)區(qū) ID 是首選跋破,因?yàn)樗鼈儾皇?DST 和時(shí)區(qū)偏移的影響。有關(guān)官方時(shí)區(qū)數(shù)據(jù)庫(kù)和維基百科中的列表瓶蝴,請(qǐng)參考 IANA毒返。
  • properties:這個(gè)元素是關(guān)于這個(gè)人的任何其他屬性所在的位置。例如舷手,指向個(gè)人圖像或即時(shí)通訊方式的鏈接拧簸。不同的插件可能會(huì)使用這些屬性,也可能只是針對(duì)閱讀 POM 的其他開發(fā)人員男窟。

contributors

<contributors> 就像開發(fā)人員一樣盆赤,在項(xiàng)目的生命周期中扮演著輔助角色。也許貢獻(xiàn)者發(fā)送了一個(gè) bug 修復(fù)蝎宇,或者添加了一些重要的文檔弟劲。一個(gè)健康的開源項(xiàng)目可能會(huì)有比開發(fā)者更多的貢獻(xià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">
  ...
  <contributors>
    <contributor>
      <name>Noelle</name>
      <email>some.name@gmail.com</email>
      <url>http://noellemarie.com</url>
      <organization>Noelle Marie</organization>
      <organizationUrl>http://noellemarie.com</organizationUrl>
      <roles>
        <role>tester</role>
      </roles>
      <timezone>America/Vancouver</timezone>
      <properties>
        <gtalk>some.name@gmail.com</gtalk>
      </properties>
    </contributor>
  </contributors>
  ...
</project>

<contributors> 包含的元素集與沒有 id 元素的開發(fā)人員包含的元素集相同姥芥。

環(huán)境設(shè)置

issueManagement

<issueManagement> 定義了所使用的缺陷跟蹤系統(tǒng)(Bugzilla、TestTrack汇鞭、ClearQuest 等)凉唐。雖然沒有什么可以阻止插件將這些信息用于某些事情庸追,但它主要用于生成項(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">
  ...
  <issueManagement>
    <system>Bugzilla</system>
    <url>http://127.0.0.1/bugzilla/</url>
  </issueManagement>
  ...
</project>

持續(xù)集成管理

在過去幾年中台囱,基于觸發(fā)器或計(jì)時(shí)器(例如淡溯,每小時(shí)或每天)的持續(xù)集成構(gòu)建系統(tǒng)越來越受到手動(dòng)構(gòu)建者的青睞。隨著構(gòu)建系統(tǒng)變得更加標(biāo)準(zhǔn)化簿训,運(yùn)行觸發(fā)器的系統(tǒng)也會(huì)觸發(fā)這些構(gòu)建咱娶。盡管大多數(shù)配置取決于所使用的特定程序(Continuum、Cruise Control,制等)强品,但也有一些配置可能發(fā)生在 POM 內(nèi)膘侮。Maven 在 <notifier> 元素中捕獲了一些重復(fù)設(shè)置。<notifier> 是通知人們某些構(gòu)建狀態(tài)的方式的榛。在以下示例中琼了,此 POM 正在設(shè)置郵件類型的通知程序,并將電子郵件地址配置為用于指定的觸發(fā)器 sendOnError夫晌、sendOnFailure雕薪,而不是 sendOnSuccesssendOnWarning

<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">
  ...
  <ciManagement>
    <system>continuum</system>
    <url>http://127.0.0.1:8080/continuum</url>
    <notifiers>
      <notifier>
        <type>mail</type>
        <sendOnError>true</sendOnError>
        <sendOnFailure>true</sendOnFailure>
        <sendOnSuccess>false</sendOnSuccess>
        <sendOnWarning>false</sendOnWarning>
        <configuration><address>continuum@127.0.0.1</address></configuration>
      </notifier>
    </notifiers>
  </ciManagement>
  ...
</project>

郵件列表

郵件列表是與人們就項(xiàng)目保持聯(lián)系的一個(gè)很好的工具晓淀。大多數(shù)郵件列表是為開發(fā)人員和用戶提供的所袁。

<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">
  ...
  <mailingLists>
    <mailingList>
      <name>User List</name>
      <subscribe>user-subscribe@127.0.0.1</subscribe>
      <unsubscribe>user-unsubscribe@127.0.0.1</unsubscribe>
      <post>user@127.0.0.1</post>
      <archive>http://127.0.0.1/user/</archive>
      <otherArchives>
        <otherArchive>http://base.google.com/base/1/127.0.0.1</otherArchive>
      </otherArchives>
    </mailingList>
  </mailingLists>
  ...
</project>
  • subscribeunsubscribe:這些元素指定用于執(zhí)行相關(guān)操作以訂閱上面的用戶列表的電子郵件地址凶掰。要訂閱上面的用戶列表纲熏,用戶將向 user-subscribe@127.0.0.1 發(fā)送電子郵件。
  • archive:此元素指定舊郵件列表電子郵件存檔的 url(如果存在)锄俄。如果存在鏡像存檔局劲,則可以在 <otherArchives> 下指定它們。
  • post:用于向郵件列表發(fā)送郵件的電子郵件地址奶赠。請(qǐng)注意鱼填,并非所有郵件列表都能夠發(fā)送到(例如構(gòu)建失敗列表)。

SCM

SCM(Software Configuration Management毅戈,也稱為 Source Code/Control Management 苹丸,或簡(jiǎn)而言之就是版本控制)是任何健康項(xiàng)目的一個(gè)組成部分。如果您的 Maven 項(xiàng)目使用 SCM 系統(tǒng)苇经,那么您可以在這里將該信息放入 POM 中赘理。

<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">
  ...
  <scm>
    <connection>scm:svn:http://127.0.0.1/svn/my-project</connection>
    <developerConnection>scm:svn:https://127.0.0.1/svn/my-project</developerConnection>
    <tag>HEAD</tag>
    <url>http://127.0.0.1/websvn/my-project</url>
  </scm>
  ...
</project>
  • connectiondeveloperConnection:這兩個(gè)連接元素表示如何通過 Maven 連接到版本控制系統(tǒng)扇单。如果連接需要讀訪問權(quán)限商模,Maven 才能找到源代碼。如果需要更新,則 developerConnection 需要提供寫訪問權(quán)限的連接施流。Maven 孵化出了另一個(gè)名為 Maven SCM 的項(xiàng)目响疚,它為希望實(shí)現(xiàn)它的任何 SCM 創(chuàng)建了一個(gè)公共 API。最受歡迎的是 CVS 和 Subversion瞪醋,但是忿晕,其他受支持的 SCM 的列表也在不斷增加。所有 SCM 連接都是通過一般的 URL 結(jié)構(gòu)進(jìn)行的银受。

    scm:[provider]:[provider_specific]
    

    其中 provider 是 SCM 系統(tǒng)的類型践盼。例如,連接到 CVS 存儲(chǔ)庫(kù)可能如下所示:

    scm:cvs:pserver:127.0.0.1:/cvs/root:my-project
    
  • tag:指定此項(xiàng)目所在的標(biāo)記宾巍。HEAD(意思是 SCM 根)應(yīng)該是默認(rèn)值咕幻。

  • url:可公開可瀏覽的存儲(chǔ)庫(kù)。例如蜀漆,通過 ViewCVS谅河。

SCM URL 的常規(guī)格式為:scm:<scm_provider><delimiter><provider_specific_part>∪范可以使用冒號(hào) : 作為分隔符绷耍,或者,如果您想將冒號(hào)用于其中一個(gè)變量(例如 Windows 路徑)鲜侥,則可以使用管道 |褂始。以下是已經(jīng)完全實(shí)現(xiàn)的 SCM:

例如,對(duì)于 Git描函,對(duì)于下面的所有 URL崎苗,我們使用冒號(hào) : 作為分隔符。如果對(duì)其中一個(gè)變量(例如 Windows 路徑)使用冒號(hào)舀寓,則使用管道 | 作為分隔符胆数。端口的分隔符在任何情況下都必須是冒號(hào),因?yàn)檫@部分是在 git URL 規(guī)范中指定的互墓。見 git-fetch 的手冊(cè)必尼。

scm:git:git://server_name[:port]/path_to_repository
scm:git:http://server_name[:port]/path_to_repository
scm:git:https://server_name[:port]/path_to_repository
scm:git:ssh://server_name[:port]/path_to_repository
scm:git:file://[hostname]/path_to_repository

示例

scm:git:git://github.com/path_to_repository
scm:git:http://github.com/path_to_repository
scm:git:https://github.com/path_to_repository
scm:git:ssh://github.com/path_to_repository
scm:git:file://localhost/path_to_repository

在某些情況下,讀寫操作必須使用不同的 URL篡撵。例如判莉,如果通過 http 協(xié)議執(zhí)行獲取,但只能通過 ssh 寫入存儲(chǔ)庫(kù)育谬,則可能發(fā)生這種情況券盅。在這種情況下,兩個(gè)URL 都可以寫入 <developerConnection> 元素中膛檀。fetch URL 必須以 [fetch=] 為前綴锰镀,push URL 必須以 [push=] 為前綴娘侍。例如:

<developerConnection>scm:git:[fetch=]http://mywebserver.org/path_to_repository[push=]ssh://username@otherserver:8898/~/repopath.git</developerConnection>

從 Maven SCM 1.3 版開始,我們假設(shè)遠(yuǎn)程倉(cāng)庫(kù)中的分支名稱與當(dāng)前本地分支的名稱相同互站。因此私蕾,無(wú)論何時(shí)調(diào)用必須訪問遠(yuǎn)程倉(cāng)庫(kù)的 maven-scm 操作僵缺,您都應(yīng)該處于該分支上胡桃。換句話說:如果沒有手動(dòng)指定分支,那么每個(gè) git-fetch磕潮、git-pull翠胰、git-push 等將始終在遠(yuǎn)程倉(cāng)庫(kù)中的分支上工作,該分支與當(dāng)前本地分支具有相同的分支名稱:

git push pushUrl currentBranch:currentBranch

provider 程序配置在 ${user.home}/.scm/git-settings.xml 中定義自脯。如下所示:

<git-settings xmlns="http://maven.apache.org/SCM/GIT/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SCM/GIT/1.1.0 http://maven.apache.org/xsd/scm-git-1.1.0.xsd">
  <revParseDateFormat/>
  <traceGitCommand/>
  <gitCommand/>
  <commitNoVerify/>
</git-settings>
  • revParseDateFormatchangelog 命令允許的 git 格式之景,默認(rèn)為 yyyy-MM-dd HH:mm:ss
  • traceGitCommand:跟蹤 git 命令的執(zhí)行膏潮《凸罚可以是 12焕参、true 或文件位置轻纪。默認(rèn)為空字符串。
  • gitCommand:git 可執(zhí)行文件的當(dāng)前名稱叠纷。默認(rèn)為 git刻帚。
  • commitNoVerify:使用選項(xiàng) --no-verify(可以防止 cygwin 出現(xiàn)尾隨空格問題)。默認(rèn)為 false涩嚣。

Prerequisites

POM 可能有某些先決條件才能正確執(zhí)行崇众。例如,Maven 2.0.3 中可能有一個(gè)補(bǔ)丁航厚,您需要它來使用 sftp 進(jìn)行部署顷歌。在 Maven 3 中,使用 Maven Enforcer 插件的 requireMavenVersion 規(guī)則或其他規(guī)則檢查其他方面幔睬。

在 Maven 2 中眯漩,這里是您為構(gòu)建提供先決條件的地方:如果不滿足這些先決條件,Maven 甚至在開始構(gòu)建之前都會(huì)失敗溪窒。POM 4.0 中唯一作為先決條件存在的元素是 <maven> 元素坤塞,它具有最小的版本號(hào)。它是用 Maven 2 檢查的澈蚌,不再出現(xiàn)在 Maven 3 中摹芙。

<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">
  ...
  <prerequisites>
    <maven>2.0.6</maven>
  </prerequisites>
  ...
</project>

Repositories

Repositories 是遵循 Maven 倉(cāng)庫(kù)目錄布局的工件集合。為了成為 Maven 倉(cāng)庫(kù)工件宛瞄,項(xiàng)目的 POM 文件的路徑必須為 $BASE_REPO/groupId/artifactId/version/artifactId-version.pom浮禾,其中交胚,$BASE_REPO 可以是本地倉(cāng)庫(kù)的文件目錄,也可以是遠(yuǎn)程倉(cāng)庫(kù)中的基本 URL盈电,其余的路徑結(jié)構(gòu)都是相同的蝴簇。

倉(cāng)庫(kù)作為收集和存儲(chǔ)工件的場(chǎng)所存在。每當(dāng)項(xiàng)目依賴某個(gè)工件時(shí)匆帚,Maven 都會(huì)首先嘗試使用指定工件的本地副本熬词。如果本地倉(cāng)庫(kù)中不存在該工件,它將嘗試從遠(yuǎn)程倉(cāng)庫(kù)下載吸重。POM 中的 <repositories> 元素指定要搜索的備用倉(cāng)庫(kù)互拾。

倉(cāng)庫(kù)是 Maven 社區(qū)最強(qiáng)大的功能之一。默認(rèn)情況下嚎幸,Maven 在以下位置搜索中央倉(cāng)庫(kù):https://repo.maven.apache.org/maven2/颜矿,可以在pom.xml 的 repositories 元素中配置其他存儲(chǔ)庫(kù)。

<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">
  ...
  <repositories>
    <repository>
      <releases>
        <enabled>false</enabled>
        <updatePolicy>always</updatePolicy>
        <checksumPolicy>warn</checksumPolicy>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <updatePolicy>never</updatePolicy>
        <checksumPolicy>fail</checksumPolicy>
      </snapshots>
      <name>Nexus Snapshots</name>
      <id>snapshots-repo</id>
      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
      <layout>default</layout>
    </repository>
  </repositories>
  <pluginRepositories>
    ...
  </pluginRepositories>
  ...
</project>
  • releases嫉晶、snapshots:這些是針對(duì)每種工件類型的策略:版本(releases)或快照(snapshots)骑疆。有了這兩個(gè)集合,POM 就可以在單倉(cāng)庫(kù)中獨(dú)立地更改每種類型的策略替废。例如箍铭,您可能決定僅啟用快照下載,可能是出于開發(fā)目的舶担。
  • enabled:表示該倉(cāng)庫(kù)是否已啟用相應(yīng)類型(releasessnapshots)的工件坡疼,為 truefalse
  • updatePolicy:該元素指定嘗試更新的頻率衣陶。Maven 將本地 POM 的時(shí)間戳(存儲(chǔ)在倉(cāng)庫(kù)的 Maven 元數(shù)據(jù)文件中)與遠(yuǎn)程 POM 進(jìn)行比較柄瑰。可以為:always剪况、daily教沾、interval:X((其中 X 是以分鐘為單位的整數(shù))、never译断。
  • checksumPolicy:當(dāng) Maven 將文件部署到倉(cāng)庫(kù)時(shí)授翻,它也會(huì)部署相應(yīng)的校驗(yàn)和(checksum)文件。在遇到校驗(yàn)和文件丟失或不一致時(shí)孙咪,您可以選擇使用ignore堪唐、failwarn 之一。
  • layout:在上面對(duì)存儲(chǔ)庫(kù)的描述中翎蹈,提到它們都遵循一個(gè)通用的布局淮菠。這基本上是正確的。Maven 2 引入的布局是 Maven 2 和 3 使用的存儲(chǔ)庫(kù)的默認(rèn)布局荤堪;然而合陵,Maven 1.x 有一個(gè)不同的布局枢赔。使用此元素可以指定默認(rèn)元素還是傳統(tǒng)元素。

Plugin Repositories

倉(cāng)庫(kù)是兩種主要類型工件的所在地拥知。第一個(gè)工件是作為依賴項(xiàng)的工件踏拜,中央倉(cāng)庫(kù)中大多數(shù)工件都是此類型。另一類工件就是插件低剔,Maven 插件本身就是一種特殊類型的工件速梗。正因?yàn)槿绱耍寮}(cāng)庫(kù)與依賴項(xiàng)倉(cāng)庫(kù)可能是分開的(然后户侥,現(xiàn)實(shí)中兩者分開的并不多)镀琉。在任何情況下峦嗤,<pluginRepositories> 元素的結(jié)構(gòu)都類似于 <repositories> 元素蕊唐。

distributionManagement

<distributionManagement> 的作用就是管理在整個(gè)構(gòu)建過程中生成的工件和支持工件的部署。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <distributionManagement>
    ...
    <downloadUrl>http://mojo.codehaus.org/my-project</downloadUrl>
    <status>deployed</status>
  </distributionManagement>
  ...
</project>
  • downloadUrl:該 URL 是 Maven 上傳部署該 POM 工件的倉(cāng)庫(kù)地址烁设,其他用戶可以從該地址下載該 POM 的工件替梨。
  • status:就像鳥巢里的小鳥,status 永遠(yuǎn)不應(yīng)該被人手觸摸装黑!原因是 Maven 將在項(xiàng)目傳輸?shù)絺}(cāng)庫(kù)時(shí)將設(shè)置項(xiàng)目的狀態(tài)副瀑。其有效類型如下所示。
    • none:無(wú)特殊狀態(tài)恋谭。這是 POM 的默認(rèn)設(shè)置糠睡。
    • converted:倉(cāng)庫(kù)的管理員將此 POM 從早期版本轉(zhuǎn)換為 Maven 2。
    • partner:此工件已與伙伴倉(cāng)庫(kù)同步疚颊。
    • deployed:到目前為止是最常見的狀態(tài)狈孔,這意味著該工件是通過 Maven 2 或 3 部署的。這是使用命令行部署階段手動(dòng)部署時(shí)得到的結(jié)果材义。
    • verified:該項(xiàng)目已驗(yàn)證均抽,應(yīng)視為已完成。
Repository

<repositories> 元素在 POM 中指定了 Maven 下載遠(yuǎn)程工件以供當(dāng)前項(xiàng)目使用的位置和方式其掂,而 <distributionManagement> 指定了該項(xiàng)目在部署時(shí)到達(dá)遠(yuǎn)程倉(cāng)庫(kù)的位置(以及方式)油挥。如果未定義 <snapshotRepository>,則 <repository> 元素將用于快照分發(fā)款熬。

<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">
  ...
  <distributionManagement>
    <repository>
      <uniqueVersion>false</uniqueVersion>
      <id>corp1</id>
      <name>Corporate Repository</name>
      <url>scp://repo/maven2</url>
      <layout>default</layout>
    </repository>
    <snapshotRepository>
      <uniqueVersion>true</uniqueVersion>
      <id>propSnap</id>
      <name>Propellors Snapshots</name>
      <url>sftp://propellers.net/maven</url>
      <layout>legacy</layout>
    </snapshotRepository>
    ...
  </distributionManagement>
  ...
</project>
  • id深寥、name:該 id 用于在眾多倉(cāng)庫(kù)中唯一標(biāo)識(shí)該倉(cāng)庫(kù),并且該 name 是易讀的形式。
  • uniqueVersion:采用 truefalse 值來表示部署到此倉(cāng)庫(kù)的工件是否應(yīng)該獲得唯一的版本號(hào)舰褪,或者使用地址中定義的版本號(hào)动漾。
  • url:這是 <repository> 元素的核心。它指定了用于將構(gòu)建工件(以及 POM 文件和校驗(yàn)和數(shù)據(jù))傳輸?shù)酱鎯?chǔ)庫(kù)的位置和傳輸協(xié)議负饲。
  • layout:這些類型和用途與存儲(chǔ)庫(kù)元素中定義的布局元素相同堤魁。它們是默認(rèn)的和遺留的。
Site Distribution

<distributionManagement> 元素不僅負(fù)責(zé)發(fā)布到倉(cāng)庫(kù)返十,還負(fù)責(zé)定義如何部署項(xiàng)目的站點(diǎ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">
  ...
  <distributionManagement>
    ...
    <site>
      <id>mojo.website</id>
      <name>Mojo Website</name>
      <url>scp://beaver.codehaus.org/home/projects/mojo/public_html/</url>
    </site>
    ...
  </distributionManagement>
  ...
</project>
  • idname洞坑、url:這些元素與上面 <distributionManagement> 中的 repository 元素中對(duì)應(yīng)元素類似盲链。
Relocation
<project xmlns="http://maven.apache.org/POM/4.0.0"1 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">
  ...
  <distributionManagement>
    ...
    <relocation>
      <groupId>org.apache</groupId>
      <artifactId>my-project</artifactId>
      <version>1.0</version>
      <message>We have moved the Project under Apache</message>
    </relocation>
    ...
  </distributionManagement>
  ...
</project>

項(xiàng)目不是靜態(tài)的,它們是有生命的東西(或垂死的東西迟杂,視情況而定)刽沾。隨著項(xiàng)目的發(fā)展,一個(gè)常見的現(xiàn)象是排拷,它們可能會(huì)被迫搬到更合適的地方侧漓。例如,當(dāng)您的下一個(gè)非常成功的開源項(xiàng)目在 Apache 保護(hù)傘下運(yùn)行時(shí)监氢,最好讓用戶知道該項(xiàng)目將被重命名為 org.apache:my-project:1.0布蔗。除了指定新地址外,提供一條解釋原因的消息也是一種很好的形式浪腐。

Profiles

POM 4.0 的一個(gè)新特性是項(xiàng)目能夠根據(jù)構(gòu)建環(huán)境更改設(shè)置纵揍。<profiles> 元素包含可選 <activation>(profile 觸發(fā)器)和一組對(duì) POM 的更改(如果該 profile 已激活)。例如议街,為測(cè)試環(huán)境構(gòu)建的項(xiàng)目與與最終部署的項(xiàng)目存在許多不同的屬性配置(諸如數(shù)據(jù)庫(kù)連接信息泽谨、關(guān)聯(lián)服務(wù)的訪問地址等)√劁觯或者吧雹,依賴關(guān)系可以根據(jù)所使用的 JDK 版本從不同的倉(cāng)庫(kù)中提取。<profiles> 元素如下所示:

<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">
  ...
  <profiles>
    <profile>
      <id>test</id>
      <activation>...</activation>
      <build>...</build>
      <modules>...</modules>
      <repositories>...</repositories>
      <pluginRepositories>...</pluginRepositories>
      <dependencies>...</dependencies>
      <reporting>...</reporting>
      <dependencyManagement>...</dependencyManagement>
      <distributionManagement>...</distributionManagement>
    </profile>
  </profiles>
</project>
激活

激活是 profile 的關(guān)鍵拾稳。profile 的威力來自于它僅在特定情況下修改基本 POM 的能力吮炕。這些情況通過 <activation> 元素指定。

<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">
  ...
  <profiles>
    <profile>
      <id>test</id>
      <activation>
        <activeByDefault>false</activeByDefault>
        <jdk>1.5</jdk>
        <os>
          <name>Windows XP</name>
          <family>Windows</family>
          <arch>x86</arch>
          <version>5.1.2600</version>
        </os>
        <property>
          <name>sparrow-type</name>
          <value>African</value>
        </property>
        <file>
          <exists>${basedir}/file2.properties</exists>
          <missing>${basedir}/file1.properties</missing>
        </file>
      </activation>
      ...
    </profile>
  </profiles>
</project>

在 Maven 3.2.2 之前访得,當(dāng)滿足一個(gè)或多個(gè)指定標(biāo)準(zhǔn)時(shí)龙亲,激活發(fā)生。遇到第一個(gè)肯定結(jié)果時(shí)悍抑,處理停止鳄炉,配置文件標(biāo)記為活動(dòng)。因?yàn)?Maven 3.2.2 激活發(fā)生在滿足所有指定標(biāo)準(zhǔn)的情況下搜骡。

  • jdkactivationjdk 元素中有一個(gè)內(nèi)置的拂盯、以 Java 為中心的檢查。如果執(zhí)行 Maven 構(gòu)建的 jdk 版本與 jdk 元素值中指定的前綴匹配记靡,則該 profile 將激活谈竿。在上面的示例中团驱,1.5.0_06 可以匹配。還支持匹配范圍空凸。有關(guān)支持范圍的更多詳細(xì)信息嚎花,請(qǐng)參閱 maven-enforcer-plugin 插件。
  • os:該元素可以定義上面所示的一些特定于操作系統(tǒng)的屬性呀洲。有關(guān)操作系統(tǒng)值的更多詳細(xì)信息,請(qǐng)參閱 maven-enforcer-plugins RequireOS 規(guī)則道逗。
  • property:如果 Maven 檢測(cè)到對(duì)應(yīng) name=value 對(duì)的系統(tǒng)屬性或命令行屬性(一個(gè)可以由 ${name} 在 POM 中取消引用的值)滓窍,則該 profile 將被激活贰您。
  • file:最后锦亦,一個(gè)給定的文件名可能通過文件的 existencemissing 來激活該 profile。注意:此元素的插值僅限于 ${basedir}令境、系統(tǒng)屬性和請(qǐng)求屬性杠园。

<activation> 元素不是激活 profile 的唯一方式。settings.xml 文件的 activeProfile 元素可能包含 profile 的 id舔庶。也可以通過在命令行的 -P 標(biāo)志(例如 -P codecoverage)后面的逗號(hào)分隔列表顯式激活抛蚁。

要查看哪個(gè)配置文件將在特定構(gòu)建中激活,請(qǐng)使用 maven-help-plugin惕橙。

mvn help:active-profiles
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞧甩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子弥鹦,更是在濱河造成了極大的恐慌肚逸,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彬坏,死亡現(xiàn)場(chǎng)離奇詭異朦促,居然都是意外死亡务冕,警方通過查閱死者的電腦和手機(jī)臊旭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門撤奸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人府喳,你說我怎么就攤上這事申窘。” “怎么了收厨?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵钦椭,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我捎拯,道長(zhǎng),這世上最難降的妖魔是什么没隘? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任瑰妄,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己宪潮,他們只是感情好食磕,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布单绑。 她就那樣靜靜地躺著,像睡著了一般苔巨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天闺魏,我揣著相機(jī)與錄音活翩,去河邊找鬼。 笑死峦树,一個(gè)胖子當(dāng)著我的面吹牛姐浮,可吹牛的內(nèi)容都是我干的肾扰。 我是一名探鬼主播偷拔,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼切端!你這毒婦竟也來了钙蒙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匙奴,沒想到半個(gè)月后啦租,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年举农,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喉悴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片今魔。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖殃姓,靈堂內(nèi)的尸體忽然破棺而出宛篇,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瞧挤。R本人自食惡果不足惜徐钠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至峰搪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凯旭,已是汗流浹背概耻。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留罐呼,地道東北人夯尽。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓潜秋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親最筒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 一府适、概述 ??當(dāng)我們使用Maven來管理和構(gòu)建我們的項(xiàng)目的時(shí)候,我們會(huì)不可避免的遇到pom文件。雖然已經(jīng)配置過po...
    騎著烏龜去看海閱讀 7,500評(píng)論 1 15
  • POM( Project Object Model缠犀,項(xiàng)目對(duì)象模型 ) 是 Maven 工程的基本工作單元间涵,是一個(gè)X...
    小宇宙_fly閱讀 234評(píng)論 0 0
  • setting.xml主要用于配置maven的運(yùn)行環(huán)境等一系列通用的屬性椒舵,是全局級(jí)別的配置文件;而pom.xml主...
    浩歌已行閱讀 747評(píng)論 0 1
  • maven的pom.xml文件配置詳解 setting.xml主要用于配置maven的運(yùn)行環(huán)境等一系列通用的屬性,...
    ProZoom閱讀 1,690評(píng)論 0 6
  • 一勤众、什么是pompom代表項(xiàng)目對(duì)象模型,它是Maven中工作的基本組成單位岖常。它是一個(gè)XML文件蟀俊,始終保存在項(xiàng)目的基...
    暗劍傷人閱讀 32,095評(píng)論 2 20