Apache Maven --- [配置文件]

配置文件的介紹html

Maven 2.0 竭盡所能的確保構建是可移植的.此外,這意味着容許構建配置在POM中,繞過全部文件系統引用(在繼承,依賴以及其餘方面),並學習更多用本地倉庫來存儲必要的元數據來使一切成爲可能.java

然而,有時候可移植性並不能徹底實現.在某些狀況下,插件可能須要使用本地文件系統路徑來進行配置.另外一些狀況下,可能須要一個略有差異的依賴集合,並且項目的工件名稱可能須要輕微的調整.還有一些狀況下,根據你的構建環境你甚至可能須要包含整個插件在構建生命週期中.web

爲了處理這些狀況,Maven 2.0 引進了構建配置文件的概念.配置文件被指定使用來自POM自己的可用元素的子集(加上一些額外的部分),並且能夠經過多種不一樣的方式來觸發.它們在構建時期修改POM,這意味着它們使用補集來爲一組目標環境提供相同但又不一樣(equivalent-but-different)的參數(例如,提供應用服務跟路徑在部署,測試,生產等環境).這樣,來自你項目組的不一樣成員的配置文件就能夠輕易的產生不一樣的構建結果.然而,恰當的使用配置文件依然能夠保持項目的可移植性.這也會最小化maven -f選項(這個選項容許用戶用不一樣的參數或者配置來建立不一樣的用於構建的POM以提升可維護性由於它只依託於一個POM運行)的使用.apache

配置文件的不一樣類型?它們在哪裏定義?bash

每一個項目app

-定義在POM自己(pom.xml)maven

每一個用戶ide

-定義在Maven-settings(%USER_HOME%/.m2/settings.xml)學習

全局測試

-定義在全局Maven-settings(${maven.home}/conf/settings.xml)

配置描述器

-位於項目基礎目錄的描述器(profiles.xml)(在Maven 3.0 中不支持)

配置文件如何被觸發?如何根據使用的配置文件的類型來實現多樣化?

一個配置文件能夠經過下列幾種方式被觸發/激活:

顯示的

經過Maven配置

基於環境變量

操做系統設置

存在或丟失的文件

配置激活詳細介紹

配置文件能夠經過使用命令行接口的-P選項顯示的激活.

這個選項提供了一個使用逗號分隔的配置文件ID列表項做爲參數來使用.當這個選項被指定的時候,選項參數中被指定的配置文件將被激活除了那些已經被激活的.

mvn groupId:artifactId:goal -P profile-1,profile-2

配置文件能夠在Maven配置中被激活,經過部分.這個部分帶有元素的列表,每個都包含有一個配置文件的ID.

<settings>
  ...
  <activeProfiles>
    <activeProfile>profile-1</activeProfile>
  </activeProfiles>
  ...
</settings>

被羅列在標籤中的配置文件將被默認激活每當項目使用它的時候.

在基於狀態檢測的構建環境中配置文件能夠被自動觸發.這些觸發器經過配置文件自己的部分來指定.通常來說,檢測被限制到JDK版本的前置匹配,系統屬性的存在或系統屬性的值.這裏有一些例子.

下面的配置將會在JDK版本是1.4.x的時候觸發配置文件:

<profiles>
  <profile>
    <activation>
      <jdk>1.4</jdk>
    </activation>
    ...
  </profile>
</profiles>

在Maven 2.1 中,範圍描述也可使用.以下描述支持1.3,1.4,1.5

<profiles>
  <profile>
    <activation>
      <jdk>[1.3,1.6)</jdk>
    </activation>
    ...
  </profile>
</profiles>

請注意:上邊界如,1.5]可能不包含大多數1.5版本,由於這裏會有一個額外的"補丁"發佈版如_05它是不被認定在這個範圍內的.

下一個激活方式是基於操做系統.更多信息請查閱:http://maven.apache.org/enforcer/enforcer-rules/requireOS.html

<profiles>
  <profile>
    <activation>
      <os>
        <name>Windows XP</name>
        <family>Windows</family>
        <arch>x86</arch>
        <version>5.1.2600</version>
      </os>
    </activation>
    ...
  </profile>
</profiles>

下面的配置文件將會在系統屬性"debug"被指定爲任意一個值的時候觸發:

<profiles>
  <profile>
    <activation>
      <property>
        <name>debug</name>
      </property>
    </activation>
    ...
  </profile>
</profiles>

下面的配置文件將會在系統屬性"environment"被指定爲"test"的時候觸發:

<profiles>
  <profile>
    <activation>
      <property>
        <name>environment</name>
        <value>test</value>
      </property>
    </activation>
    ...
  </profile>
</profiles>

爲了激活這個配置文件,你須要執行:

mvn groupId:artifactId:goal -Denvironment=test

從Maven 3.0 起,在POM中的配置文件能夠被激活基於來自settings.xml中的已激活文件的屬性.

請注意:環境變量像做爲env.FOO的屬性的FOO是可用的.進一步注意到在Windows上環境變量的規範命名要求所有大寫.

配置文件將會激活當生成的文件target/generated-sources/axistools/wsdl2java/org/apache/maven丟失時:

<profiles>
  <profile>
    <activation>
      <file>
        <missing>target/generated-sources/axistools/wsdl2java/org/apache/maven</missing>
      </file>
    </activation>
    ...
  </profile>
</profiles>

自Maven 2.0.9 起,標籤和能夠被插入.支持的值是系統屬性如${user.name}和環境變量如${env.HOME}.請注意定義在POM自身中的屬性和值是不能被插入的.如:上面例子中的激活劑不能使用${project.build.directory}除非硬編碼路徑target.

配置文件也能夠經過使用下面的配置來默認激活:

<profiles>
  <profile>
    <id>profile-1</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    ...
  </profile>
</profiles>

這個配置文件對於全部構建將會被自動激活除非在相同的POM中有另外一個配置文件已經經過以前描述過的方法被激活.全部已經激活的配置文件將會默認自動失效當一個POM中的配置文件是經過命令行或者它的activation配置激活.

失效一個配置文件

從Maven 2.0.10 開始,一個或多個配置文件能夠失效化經過執行帶有前綴"!"或"-"匹配它們標識符的命令行來實現,像這樣:

mvn groupId:artifactId:goal -P !profile-1,!profile-2

這能夠用來失效被默認激活的配置文件或那些經過它們的activation配置激活的配置文件.

POM中的哪些區域能夠自定義配置文件類型?爲何?

如今咱們已經討論了在哪裏指定配置文件,如何激活它們,那麼討論咱們能夠在一個配置文件中指定什麼內容將會是頗有用的.和配置文件的其餘方面同樣,答案並不簡單.

依賴於你選擇在哪裏配置的你的配置文件,你將會訪問不一樣的POM配置選項.

外部配置文件

配置文件被指定到外部文件(如:settings.xml和profiles.xml)在嚴格意義上來說是不可移植的.任何彷佛能夠忍受構建結果高可變性的是被限制在POM的內聯配置文件上的.如倉庫列表僅僅是那些被承認的工件的專用倉庫,並且不會改變構建輸出.所以,你將只能夠修改和部分,加上額外的部分.

部分容許你爲POM指定自由來源的鍵值對,它們將在插入處理過程當中被包含進來.這容許你用${profile.provided.path}的格式來指定一個插件配置.

POM中的配置文件

另外一方面,若是你的配置文件能夠被合理的指定在POM中,那麼你將有更多選擇.固然,權衡點是你只能修改項目和它的子模塊.由於這些配置文件被內聯指定,因此咱們能夠更好的保持可移植性,這是合理的,你能夠添加更多的信息而沒必要擔憂這些信息不能被其餘用戶所使用.

指定在POM中的配置文件能夠修改以下POM元素:

<repositories>
<pluginRepositories>
<dependencies>
<plugins>
<properties> (在主要POM並非真實可用的,可是在幕後運行)
<modules>
<reporting>
<dependencyManagement>
<distributionManagement>
<build>元素的子集,包括:
<defaultGoal>
<resources>
<testResources>
<finalName>

配置文件的誤區

咱們已經說起了添加配置文件到你的構建中存在潛在的可能性會破壞你項目的可移植性.咱們甚至已經強調了配置文件可能會破環項目可移植性的那些狀況.然而,這仍然是很值得來針對這些誤區作一個連貫的討論來重申這些關鍵點以便於咱們在使用配置文件時能夠規避它們.

當咱們使用配置文件的時候,主要有兩大問題須要記住.首先是外部屬性一般在插件配置中使用,這些形成了破壞你項目可移植性的風險.其次,配置文件集合中更微妙的區域是不徹底指定的.

外部屬性

外部屬性定義涉及到那些定義在pom.xml外部可是又不是定義在對應的配置文件內的屬性值.POM中的屬性最明顯的用處就是用於插件配置.然而沒有屬性確實有可能會破壞項目的可移植性,它們會產生細微的影響致使構建失敗.例如,指定一個被配置在settings.xml中的應用服務路徑可能引發你的集成測試插件失敗當另外一個團隊中的用戶視圖構建項目卻又沒有相似的settings.xml時.考慮下面的一個Web應用項目的POM片斷:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.myco.plugins</groupId>
        <artifactId>spiffy-integrationTest-plugin</artifactId>
        <version>1.0</version>
        <configuration>
          <appserverHome>${appserver.home}</appserverHome>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

如今,在你的本地存在${user.home}/.m2/settings.xml:

<settings>
  ...
  <profiles>
    <profile>
      <id>appserverConfig</id>
      <properties>
        <appserver.home>/path/to/appserver</appserver.home>
      </properties>
    </profile>
  </profiles>
 
  <activeProfiles>
    <activeProfile>appserverConfig</activeProfile>
  </activeProfiles>
  ...
</settings>

當你構建integration-test生命週期階段時,你的集成測試將會經過,由於你提供的路徑容許測試插件安裝並測試這個web應用.

然而,當你的同事視圖構建integration-test時,他的構建會失敗,抱怨說它不能解決插件配置參數<appserverHome>,或者更糟,參數${appserver.home}的值是無效的.

恭喜,你的項目如今是不可移植的.將這個配置文件內聯到你的POM能夠緩解這個問題,隨之而來的明顯的缺點是每一個項目層級如今都不得不指定這個信息.由於Maven爲項目繼承提供了很好的支持,將這種配置粘貼到組級別POM中的<pluginManagement>部分去更加合理,並且能夠輕易繼承路徑值.

另外一個回答多是開發環境的標準化.然而,這會損害Maven可以提供的生產收益.

天然配置文件集的不徹底指定

除了上面的可移植性破壞者以外,經過配置文件來覆蓋全部狀況也很容易失敗.當你這麼作的時候,你一般會遺留一種目標環境處於孤立無援的境地.讓咱們看例子,再次展現和上述同樣的POM片斷:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.myco.plugins</groupId>
        <artifactId>spiffy-integrationTest-plugin</artifactId>
        <version>1.0</version>
        <configuration>
          <appserverHome>${appserver.home}</appserverHome>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

如今,考慮以下配置文件,哪個將被內聯指定到pom.xml:

<project>
  ...
  <profiles>
    <profile>
      <id>appserverConfig-dev</id>
      <activation>
        <property>
          <name>env</name>
          <value>dev</value>
        </property>
      </activation>
      <properties>
        <appserver.home>/path/to/dev/appserver</appserver.home>
      </properties>
    </profile>
 
    <profile>
      <id>appserverConfig-dev-2</id>
      <activation>
        <property>
          <name>env</name>
          <value>dev-2</value>
        </property>
      </activation>
      <properties>
        <appserver.home>/path/to/another/dev/appserver2</appserver.home>
      </properties>
    </profile>
  </profiles>
  ..
</project>

這個配置文件看起來和上一個例子中的至關相似,但也有些重要的區別:顯然這是面向一個開發環境的,一個名叫 appserverConfig-dev-2 的配置文件被添加了進來,而且它包含了activation部分這會使得它被激活使用當系統屬性包含"env=dev"對應於appserverConfig-dev而"env=dev2"對應於appserverConfig-dev-2.因此,執行:

mvn -Denv=dev-2 integration-test

的結果是構建成功,應用來自配置文件appserverConfig-dev-2的屬性.而當執行:

mvn -Denv=dev integration-test

的結果也是構建成功,應用來自配置文件appserverConfig-dev的屬性.然而,執行:

mvn -Denv=production integration-test

的結果是構建失敗.爲啥?由於對於部署和測試你的web應用來講${appserver.home}變量的字面值是不可用的路徑.當咱們書寫咱們的配置文件的時候沒有考慮生產環境."production"環境(env=production)和"test",甚至可能"local"組成一個目標環境的天然集合讓咱們用來構建集成測試生命週期階段.天然集的不徹底指定意味着咱們實際上限制了可用的目標環境到開發環境.你的組員或你的上司,不會想看這種笑話.當你像這樣構造配置文件的時候,請確保解決了整個目標集的排列.

順帶一提,特定於用戶(user-specific)的配置文件也能夠以一種相似方式操做.這意味着那些支持各類不一樣環境的配置文件是以用戶爲key的,並且當團隊新增了一個開發人員的時候他將無法正常運行.然而我認爲這對於新手來講是至關有用的訓練,這是有些不大友好將他們扔進了狼羣...再次強調,請確保考慮了配置文件的完整集合.

我如何判斷哪個配置文件在構建期間起做用?

肯定激活的配置文件將幫助咱們瞭解哪些具體配置文件在構建期間被執行.咱們可使用Maven Help Plugin 的以下命令來辨別:

mvn help:active-profiles

讓咱們看些小例子來幫咱們瞭解更多關於這個插件的 active-profiles 目標.

在上一個例子pom.xml中的配置文件中,你會發現這裏有兩個配置文件appserverConfig-dev和appserverConfig-dev-2,它們給出了不一樣的屬性值.若是咱們執行:

mvn help:active-profiles -Denv=dev

結果將會展現activation屬性的值是"env=dev"的配置文件的ID以及它在哪一個資源中被聲明的:

The following profiles are active:
 
 - appserverConfig-dev (source: pom)

如今若是咱們有一個聲明在settings.xml中的配置文件並且他已經設置了成一個active的配置文件,執行:

mvn help:active-profiles

結果將會是這樣的:
 

The following profiles are active:
 
 - appserverConfig (source: settings.xml)

即便咱們沒有activation屬性,一個配置文件也別列在了激活列表中.爲啥?像咱們以前提到的,一個在settings.xml中被設置爲active的配置文件是自動激活的.

如今若是咱們在settings.xml中有個設置爲active的配置文件,而在POM中也觸發了一個相同的配置文件.你認爲哪一個配置文件在構建過程當中生效?

mvn help:active-profiles -P appserverConfig-dev

這將展現激活的配置文件:

The following profiles are active:
 
 - appserverConfig-dev (source: pom)
 - appserverConfig (source: settings.xml)

即便它列出了兩個激活的配置文件,但咱們沒法確認哪一個真正被應用.執行:

mvn help:effective-pom -P appserverConfig-dev

這將會打印出構建配置中有效的POM到控制檯.注意在settings.xml中的配置文件的優先級高於POM中的.因此真正應用的配置文件是appserverConfig而不是appserverConfig-dev.

若是你想將輸出指向到一個叫effective-pom.xml的文件,使用命令行選項:-Doutput=effective-pom.xml.

命名約定

到如今爲止咱們已經知道配置文件是處理針對不一樣目標環境使用不一樣的構建配置問題的一種天然方式.此前,咱們討論了配置文件"天然集合"的概念來處理這種狀況,以及考慮配置文件的完整集合的重要性.

然而,如何組織和管理集合的演變問題也很重要.就像一個優秀的開發人員努力編寫自描述的代碼同樣,給你的配置文件起一個能明顯暗示它的使用意圖的ID也很重要.一個好的實踐方式是使用經常使用系統屬性觸發器做爲你的配置文件名稱的一部分.結果多是像這樣:env-dev,env-test和env-prod這些配置文件是被系統屬性env所觸發的.這樣一個系統留下了很是直觀的暗示來告知如何激活一個構建目標針對特定的環境.所以,爲了爲測試環境激活一個構建,你須要激活env-test經過發行:

mvn -Denv=test <phase>
相關文章
相關標籤/搜索