這是一個Maven提高篇的系列,包含有以下文章:
- Maven提高篇系列之(一)——多模塊 vs 繼承
- Maven提高篇系列之(二)——配置Plugin到某個Phase(以Selenium集成測試為例)
- Maven提高篇系列之(三)——使用自己的Repository(Nexus)
- Maven提高篇系列之(四)——使用Profile
- Maven提高篇系列之(五)——處理依賴沖突
- Maven提高篇系列之(六)——編寫自己的Plugin(本系列完)
在開發項目時,設想有以下場景:
-
你的Maven項目存放在一個遠程代碼庫中(比如github),該項目需要訪問數據庫,你有兩台電腦,一台是Linux,一台是Mac OS X,你希望在兩台電腦上都能做項目開發。但是,安裝Linux的電腦上安裝的是MySQL數據庫,而Mac OS X的電腦安裝的是PostgreSQL數據庫。此時你需要找到一種簡單的方法在兩種數據庫連接中進行切換,你會怎么做?
-
此外,你的項目需要部署。為了調試,在開發時我們在Java編譯結果中加入了調試信息(Java默認)。而在部署時你希望Java編譯結果中不出現調試信息。此時你又會怎么做?
答案是Profile。Maven的Profile用於在不同的環境下應用不同的配置。一套配置即稱為一個Profile。這里的“環境”可以是操作系統版本,JDK版本或某些文件是否存在這樣的物理環境,也可以是你自己定義的一套邏輯環境。比如上面的A中所說的Linux和Mac OS X便是一種物理環境,而B中講的開發環境和部署環境則為邏輯環境。Maven提供了Activation機制來激活某個Profile,它既允許自動激活(即在某些條件滿足時自動使某個Profile生效),也可以手動激活。
一個Profile幾乎可以包含所有能夠出現在pom.xml中的配置項,比如<artifactId>,<outputDirectory>等。相當於在Profile中定義的配置信息會覆蓋原有pom.xml中的相應配置項。
(一)定義Profile
一般來說,我們將Profile的定義放在pom.xml文件的最后:
<profiles> <profile> <id>apple</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <fruit>APPLE</fruit> </properties> </profile> <profile> <id>banana</id> <properties> <fruit>BANANA</fruit> </properties> </profile> </profiles>
在上面的配置中,我們定義了兩個Profile,一個id為apple,該Profile將fruit屬性設置為APPLE,另一個id為banana,它將fruit屬性設置為BANANA。此外,第一個Profile還配置了“<activeByDefault>true</activeByDefault>”,表明該Profile默認即是生效的。
為了打印出fruit這個屬性,我們再向pom.xml中添加一個maven-antrun-plugin插件,我們可以通過該插件的echo任務來打印屬性信息。我們將該打印配置在Maven的initialize階段(任何階段都可以):
<plugin> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <phase>initialize</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>Fruit:${fruit}</echo> </tasks> </configuration> </execution> </executions> </plugin>
配置完成之后,執行:“mvn initialize”,由於id為apple的Profile默認生效,此時將在終端輸出“APPLE”字樣:
...... [INFO] Executing tasks [echo] Fruit:APPLE [INFO] Executed tasks ......
如果要使用id為banana的Profile,我們可以顯式地指定使用該Profile:"mvn initialize -Pbanana":
...... [INFO] Executing tasks [echo] Fruit:BANANA [INFO] Executed tasks ......
(二)手動激活Profile
事實上,在上面的例子中,我們在顯示“BANANA”時便使用了手動激活Profile的方式。手動激活Profile要求我們在運行mvn命令時通過“-PprofileId”的方式指定使用某個Profile。比如,對於上文提到的B點,我們可以通過一下配置完成:
<profile> <id>production</id> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <debug>false</debug> </configuration> </plugin> </plugins> </build> </profile>
在開發時,我們使用“mvn clean install”,此時名為production的Profile並沒有被激活,所以還是采用Java編譯默認的配置(即在結果中包含了調試信息)。當需要為生產部署環境編譯時,便可以使用“mvn clean install -Pproduction”。
本人認為,Maven的Profile機制最大的好處在於它的自動激活性(請參考下文),因為如果手動激活,在運行mvn命令時我們依然需要告訴Maven一些信息(即這里的“-PprofileId”)來完成配置,我們完全可以通過另外的方法來達到相同的目的。比如,我們可以定義一個父pom和兩個子pom(比如pom.xml和pomB.xml),在父pom中我們存放兩個子pom共享的配置(比如上面的maven-antrun-plugin),而在兩個子pom中分別配置不同的信息以代表不同的環境,比如在pom.xml中(默認執行的pom),我們將fruit屬性設置成APPLE,而在pomB.xml中,將fruit屬性設置成BANANA。此時,pom.xml和pomB.xml都繼承自父pom。雖然在默認情況下Maven會將名為“pom.xml”的文件作為輸入文件,但是我們通過“-f”參數來指定其他pom文件。比如,如果我們要顯示“APPLE”,我們可以直接執行“mvn initialize”,如果要顯示“BANANA”,則可以執行“mvn initialize -f pomB.xml”。
(三)自動激活Profile
在自動激活Profile中,我們需要為某個Profile預先定義一些前提條件(比如操作系統版本),當這些前提條件滿足時,該Profile將被自動激活。比如,對於上文中的A點,我們可以為Mac OS X和Linux(Unix)分別定義一套數據庫連接:
<profile> <id>mac</id> <activation> <activeByDefault>false</activeByDefault> <os> <family>mac</family> </os> </activation> <properties> <database.driverClassName>org.postgresql.Driver</database.driverClassName> <database.url>jdbc:postgresql://localhost/database</database.url> <database.user>username</database.user> <database.password>password</database.password> </properties> </profile> <profile> <id>unix</id> <activation> <activeByDefault>false</activeByDefault> <os> <family>unix</family> </os> </activation> <properties> <database.driverClassName>com.mysql.jdbc.Driver</database.driverClassName> <database.url>jdbc:mysql://localhost:3306/database</database.url> <database.user>username</database.user> <database.password>password</database.password> </properties> </profile>
請注意,以上兩個Profile在默認情況下都沒有被激活,Maven在運行時會檢查操作系統,如果操作系統為Mac OS X,那么Maven將自動激活id為mac的Profile,此時將使用PostgreSQL的數據庫鏈接,如果操作系統為Linux或Unix,那么將使用MySQL數據庫連接。更多的Profile自動激活條件,請參考此文檔。
在下一篇文章中,我們將講到如何處理依賴沖突。