【Maven】【翻譯】3、Profiles文件

本文根據 Maven profiles文件介紹翻譯:

一、構建Profiles配置文件介紹;

Apache Maven 2.0 工程在保證構建過程更便捷起了非常大的作用;除了其他特例,它允許在POM裏構建配置,這樣就避免了所有文件系統相關的麻煩(繼承,依賴和其他地方),並且避免在本地倉庫學習太多來存儲實現的原始數據;

然鵝,有時候可移植性是不完全支持的;在某些情況下,插件可能需要在本地文件系統路徑下配置。另一些情況下,一個些輕微不同的依賴設置是必須的,並且項目的產品名稱可能需要做輕微的調整。並且在其他時候,在掃描構建環境的時候,你可能甚至需要包括構建Maven生命週期的所有插件的依賴;

爲了定位這些情況,Maven2.0引入了profile的概念;profiles是爲了POM文件自身(可能還有其他部分)中可用元素而特別定義的;並且會被多種途徑觸發;在構建時期,他們會修改POM文件,並且被用來完善設置目標環境等價但是不完全相同的參數(例如,開發,測試和生產環境app服務器的根目錄);因此,profiles可以輕易的搭建一個你團隊不同成員的不同構建結果;然而,正式使用時,profiles可以在保留項目可移植性而使用。這會盡量減少-f 操作(Maven允許用戶根據不同的參數或配置創建另一個POM,以此在唯一一個POM運行時,來構建可維護性 )

二、profile類型之間的不同,每個是在哪定義的;

  • 每個項目 :在POM文件本身裏定義(pom.xml).
  • 每個用戶:在Maven的settings文件裏定義 (%USER_HOME%/.m2/settings.xml).
  • 全局配置: 在全局的Maven的settings 文件裏配置(${maven.home}/conf/settings.xml).
  • 在Profile定義:一個定義在項目根目錄中的腳本 (profiles.xml) (Maven 3.0中不支持:詳情參看 Maven 3 compatibility notes)

三、一個profile怎樣被觸發的?根據已用的profile類型如何變化的?

一個profile文件可以被以下幾種情況出發:

  • 明確定義
  • 通過Maven的settings文件配置
  • 機遇環境變量
  • OS的settings文件
  • 存在或丟失文件
    3.1、profile操作詳解
    Profiles可以通過CLI命令行操作,使用-p 命令。
    這個操作需要你使用用逗號分隔的profile文件的ID。當這個動作被定義了,profiles文件會定義動作,並且在任何profiles文件中可以通過激活配置或者通過settings.xml文件中的<activeProfiles>標籤來被激活;
mvn groupId:artifactId:goal -P profile-1,profile-2

Profiles文件可以在Maven的settings文件中,通過<activeProfiles>標籤來激活;這個標籤可以通過<activeProfile> 標籤,每個標籤裏都包含profile文件的ID;舉例如下:

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

Profiles在<activeProfiles>標籤裏會在每次該項目被使用時激活;
Profiles在構建環境是,可以被偵測到並自動激活;這個觸發器會被定義在profile文件的<activeProfiles> 標籤裏;目前,這個標籤被JDK的版本,系統性能的表現或系統性能的值所限制;下面是例子

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

在Maven 2.1中,可以被使用的範圍(可以查找Enforcer Version Range Syntax 獲取更多信息)。下面的是1.3,1.4,1.5版本的;

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

注意:一個更高的邊界,例如 ,1.5] 更可能不包括1.5。自從他們添加了額外的patch發行版,例如 _05,是不被上面的範圍考慮進去的;
下一個會被激活的情況是OS(Operating System-操作系統)的settings配置文件;請參看Maven Enforcer Plugin 獲取關於OS值詳情的信息;

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

下面可以通過系統屬性的【debug】的值來特別定義,使prifile被激活:

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

下面通過系統屬性的【debug】模式不能激活profile

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

如果配置了系統屬性沒有定義【debug】或者定義了【debug】屬性,但是值爲非真,那麼也不會激活;

    <profiles>
      <profile>
        <activation>
          <property>
            <name>debug</name>
            <value>!true</value>
          </property>
        </activation>
        ...
      </profile>
    </profiles>

爲了激活,你需要在CLI命令行輸入下面命令之一:

mvn groupId:artifactId:goal
mvn groupId:artifactId:goal -Ddebug=false

下一個例子可以通過定義環境系統屬性爲test,來激活配置

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

爲了激活該配置,你需要在CLI命令行執行下面命令:

mvn groupId:artifactId:goal -Denvironment=test

在Maven 3.0版本中,POM中的profiles文件可以通過settings.xml文件中的屬性來激活:
注意:環境變量中的FOO是作爲env.FOO的屬性的變量。此外,還應注意到環境變量的名字是Windows系統中的駝峯命名法。下面的例子可以出發profile文件,當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版本,標籤<exists> and <missing>的值可以被修改的,支持例如 ${user.home} 這樣的系統變量,例如${env.HOME}的環境變量。注意定義在POM文件中的屬性和值是不允許修改的;上面的例子激活器不能夠使用${project.build.directory},但是需要硬式編碼target的路徑;
Profiles 可以同樣的被下面的配置激活

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

這個profile可以自動的被所以編譯自動激活,除非另一個相同的POM文件中有一個profile已經有限描述了該方法被激活了。當一個POM文件中的profile文件通過CLI命令或者配置被激活,所有的profiles文件會被默認自動激活,自動失效;
3.1、失效一個profile文件
Maven 2.0.10開始,可以通過CLI命令來預配置他們的【!】或者【-】標識符,來使一個或多個profiles文件可以被失效,舉例如下:

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

這可以是profiles文件被activeByDefault失效,否則profiles將會被激活配置激活;

四、POM文件中哪個地方可以被profile自定義?爲什麼?

現在,我們談了怎樣特別定義一個profiles,並且如何激活他們,討論如何定義一個profile文件很有意義;profile文件配置的其他方面,這裏答案是不明確的;
依賴於你再profile文件中選擇的配置,你會有多重配置POM選項;

4.1、外部文件的Profiles
在外部文件定義profiles文件(例如settings.xml或profiles.xml)嚴格意義上說是不便捷的;任何在POM正文裏的構建結果,看上去改變的可能性很大;像repository倉庫列表一樣思考,它可以很簡單的被嚴格壟斷認證,並且不會改變構建的結果;因此,你可以僅僅修改<repositories> and <pluginRepositories> 標籤,外加一個<properties>標籤;

<properties>標籤允許你特別定義自由格式的鍵值對,這些鍵值對會被包括在POM文件中。這允許你以${profile.provided.path}的形式來定義你的插件配置;

4.2、POMs文件中的Profiles;
另一方面,如果你的profiles文件可以在POM文件裏合理的定義,你可以有多重選擇;權衡利弊,你可以僅僅修改項目和子模塊;自從這些profiles文件可以在POM內部定義,因此有更好的機會保證其可移植性;你添加更多的信息而不帶來其他用戶不可使用的風險是非常合理的;

POM文件中的Profiles文件可以修改下列標籤:

<repositories>
<pluginRepositories>
<dependencies>
<plugins>
<properties> (不僅僅在主POM文件,並且可以被用在場景後)
<modules>
<reporting>
<dependencyManagement>
<distributionManagement>
<build>標籤的子集, 由下列標籤組成:
<defaultGoal>
<resources>
<testResources>
<finalName>

4.3、<profiles> 標籤外的POM文件
我們不允許在POM的profiles文件外修改POM標籤,因爲這些運行時修改,在POM部署到倉庫系統時不會是分佈的,會使一個人構建的項目和其他人不一樣;當你通過外部profiles文件來操作某些場景時,風險是可控的;另一個原因是POM文件信息可以被父POM複用;

外部文件,例如settings.xml和profiles.xml文件同時不支持外部的POM的profiles文件。讓我們精心構建下場景。當有效的POM文件從一個遠程的倉庫部署時,任何人可以在倉庫外獲取其信息,並且使用這些來直接構建一個Maven項目。現在,想象一下,我們可以在依賴中設置profiles文件,這對於構建來說,很重要。或者,在settings.xml文件中的,POM的profiles之外的標籤,最可能的是,我們不希望其他使用倉庫的POM,並且可以構建它。我們還考慮到如何跟其他人分享settings.xml;注意,再多的配置文件會讓人混亂並且難以維護。我們的底線是,只要開始構建數據了,它必須在POM中。Mavne 2的一個目標就是鞏固需要運行的單個文件的構建,或者讓POM文件分級;

五、profile陷阱;

我們已經提到了一個事實,添加profiles文件來構建有破壞可移植性的潛在風險。我們甚至強調了概要文件可能破壞項目可移植性的情況。然而,重申這些關於一些避坑的,重點清晰的論點是非常有意義的;

當你使用profiles時,這裏有兩個主要的問題必須注意;
1、外部的屬性,通常在插件配置中。這會造成你項目可移植性變差;
2、更微妙的領域是對一組自然概要文件的不完整規範。

5.1、外部屬性
額外的屬性定義設計定義在POM.xml文件外的任何屬性值的定義,但是沒定義在同一個profiles文件裏的;這通常能在POM中的插件配置裏看到屬性的使用;當沒有屬性時,很可能會破壞其可移植性,這些怪異可以以微妙的影響造成構建失敗;例如,只在settings.xml文件中的profile中指定了app服務器的路徑,當另一個團隊用戶試圖在沒有類似的settings.xml文件的情況下構建,可能導致你的集成測試插件失敗;考慮到下面的pom.xml ,一個爲web程序項目的片段

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

當你構建集成測試生命週期階段,你的集成測試通過,在這個你提供的允許測試插件來安裝和測試web項目的路徑。
然而,當你同時試圖構建集成測試時,他構建卻慘烈地失敗了,抱怨這個不能解析<appserverHome> 這個參見配置參數,甚至更糟糕的是,合法的參數的值${appserver.home} 卻獲取不到;

值得慶幸的是,你的項目現在不可移植。在profile文件裏嵌入你的pom.xml文件可以幫助緩和這個情況,這裏明顯的缺陷是,每個項目的層級(允許繼承的影響)都會明確這些信息。自從Maven爲項目繼承提供了很好的支持,它允許團隊級別在POM文件添加這種<pluginManagement> 標籤,並且簡單繼承這種路徑;

另外,更少的吸引人的答案可能讓開發環境更標準化;然而,這會增加對Maven開發效率的妥協;

5.2、不完善的自然的profile配置說明
除了上面的可移植性破壞,覆蓋所有profiles文件會很容易導致失敗;當你做這部分工作時,你常常會使你的目標環境很高和枯燥。下面舉了一個POM.xml例子,還是使用上面的片段:

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

現在,考慮到下面的profiles,這個可以在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>

這個profiles配置文件看上去和上個例子很相似,但是有一點導入異常:它明確地與開發環境相適應;一個新的名爲appserverConfig-dev-2 的profile文件被添加,並且它有一個激活的標籤,在名爲 appserverConfig-dev 的profile裏,系統屬性包含env=dev 和在名爲 appserverConfig-dev2 的profile裏包含系統屬性 env=dev-2;這會使得它在內部出發;所以,執行以下命令

mvn -Denv=dev-2 integration-test

會導致成功構建,應用名爲 appserverConfig-dev-2 的 profile,並且我們需要執行

mvn -Denv=dev integration-test

在應用了名爲 appserverConfig-dev 的profile文件所給定屬性,他講構建成功。然後執行:

mvn -Denv=production integration-test

這不會構建成功。爲什麼?因爲${appserver.home} 是不允許修改的;這不是一個你web項目部署和測試的有效的路徑。我們在寫profiles文件是不考慮產品環境的情況。產品環境指的是 env=production ,而且還可以是“test”,並且甚至可能是“local”組成的一個爲我們可能構建的集成測試的生命週期階段的自然的目標環境集合;未完成的自然集合的聲明意味着我們可以有效的限額的可獲得的開發的目標環境;你的同事-或者你的經歷-將不再看到你的笑話;當你構造profiles文件來處理這些情況時,只要確認添加了完整的目標列表地址集即可;

順便提一下,這允許用戶使用自定義的profiles在相似環境開發;這意味着,profiles用來處理不同的環境是用戶可以成功添加新開發者的關鍵;我支持這樣用來訓練網絡新手,把他們像綿羊一樣丟給狼羣可能顯得不太友好,但是,要考慮到整體的profiles集合;

六、我如何辨別構建過程中哪些profiles是有效的?

決定有效的profiles文件可以幫助用戶知道在構建過程中,哪些profiles文件可以被執行。我們可以使用Maven Help Plugin 來告訴我們構建過程中哪些profiles是有效的;

mvn help:active-profiles

讓我們舉一些小例子來幫助我們理解這個插件中的有效profiles。
上一個pom.xml裏profiles的例子,你需要注意,這裏有兩個profiles的標籤:appserverConfig-devappserverConfig-dev-2 ,這樣可以爲屬性賦不同的值。如果我們繼續執行:

mvn help:active-profiles -Denv=dev

這個結果會執行激活所有定義了的狀態的屬性爲 env=dev 的所有profiles列表;

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

現在,如果我們有一個定義在settings.xml 裏的profile文件(關聯settings.xml中的profile配置例子),並且有一個激活的profile文件來執行;

  mvn help:active-profiles

結果會如下所示:
The following profiles are active:

  • appserverConfig (source: settings.xml)

儘管我們沒有配置激活屬性,但是一個激活的profile列表已經被激活了。爲什麼?像我們之前提到過的一樣,一個settings.xml中設置的profile標籤會自動被激活;

現在,如果我們有settings.xml文件中的profile文件,並且被設置成激活的profile,而且已經在POM中被觸發了;你猜哪個在構建會生效?

 mvn help:active-profiles -P appserverConfig-dev

結果會顯示如下:
The following profiles are active:

  • appserverConfig-dev (source: pom)
  • appserverConfig (source: settings.xml)

儘管,它列出了兩個profiles部分,但是我們不缺定哪個被應用了;請看構建執行時的生效狀態:

  mvn help:effective-pom -P appserverConfig-dev

它會打印出構建配置的有效的POM文件到控制檯;注意settings.xml中的profiles會比POM中的profiles文件具有更高的權限;所以被應用的是appserverConfig 而非 appserverConfig-dev

如果你想重定向插件到一個名爲 effective-pom.xml 的插件,使用命令行操作:

-Doutput=effective-pom.xml

七、命名慣例;

現在,你注意到profiles是一個很自然的爲不同的目標環境,將不同的構建配置添加問題;以上,我們討論了【自然配置】profilesl來添加這些情景,並且意識到profiles需要的所有設置的重要性;

然而,如何組織和管理版本演化也是非常重要的。就像一個優秀的開發者會【自我文檔化】編碼;在設計使用時給你的profiles部分的id會給出重要提示是非常重要的。一個很好的方法就是使用普通系統屬性觸發器作爲profile的部分名字;這會導致,使一些像env-dev,env-test和env-prod作爲profiles文件名能夠被系統屬性env出發;例如一個系統留下了憑直覺給提示:如何在一個特定的環境裏激活一個構建目標。因此,要激活一個測試環境的構建,你需要激活 env-test 來驅動;

mvn -Denv=test <phase>

這種正確的命令行操作可以簡單的被“=”來取代profile部分的id中的“-”;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章