構建項目時可能會遇到在測試(如單元測試)、開發、模擬、生產等不同環境下需要不同配置(properties、xml)或資源(jpg、png、mp3)的情況。比如常見的數據庫連接(即 jdbc url)的值,在不同的環境下可能有如下幾種值:
· 測試環境:jdbc:mysql://localhost:3306/foobar_test
· 開發環境:jdbc:mysql://localhost:3306/foobar_dev
· 模擬環境:jdbc:mysql://192.168.1.11:3306/foobar
· 生產環境:jdbc:mysql://192.168.1.10:3306/foobar
或者同樣是生產環境,針對(產品)交付給A公司客戶的與交付給B公司客戶的需要不同配置或者資源,比如產品界面中的公司名稱、公司LOGO等。
又或者針對不同的操作系統(如 Windows,Linux)需要爲某個配置設定不同的文件路徑。
可見,在不同的軟件開發生命週期階段、不同的最終客戶(用戶)環境、不同的運行平臺都有可能需要不同配置或資源的情況。假如各個環境下的差別很小的話,我們可以在項目編譯之後手工修改或者寫個 shell script 自動修改,但如果需要修改的項目很多而且複雜的話,則應該使用 Apache Maven 的 Profile 和 Filtering 功能來解決。(當然前提是你的項目必須是用 Maven 構建的啦,哈哈,還有測試階段所使用到的資源文件實際上 Maven 默認已經劃分出來,所以並不需要本文所說的方法)
Filtering 功能
Filtering 是 Maven Resources Plugin 的一個功能,它會使用系統屬性或者項目屬性的值替換資源文件(*.properties,*.xml)當中 ${…} 符號的值。比如你係統屬性有一項 “user.name=foobar”,那麼資源文件當中的 ${user.name} 符號會在 Maven 編譯時自動被替換爲 “foobar”。
舉個例子:
默認的項目資源文件位於 “src/main/resources” 目錄,在該目錄下創建一個文件 “test.properties”,裏面寫上一行:
Hello ${user.name}
然後修改項目文件(pom.xml)啓用 filtering 功能,如:
<project> ... <build> ... <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> ... </resources> ... </build> ... </project> |
然後編譯項目:
$mvn clean compile -Duser.name=foobar |
查看輸出文件 target/classes/test.properties 的內容,可見原先的 “Hello {user.name}” 已經變成 “Hello foobar”。
我們也可以把 filtering 用到的變量寫在項目屬性段裏,比如:
<project> ... <properties> <user.name>foobar</user.name> <user.email>[email protected]</user.email> </properties> ... </project> |
如果屬性項比較多的話,最佳實踐是把他們抽離出來獨立一個屬性文件,比如在你項目目錄(即 pom.xml 文件所在的目錄)新建一個屬性文件 project.properties:
user.name=foobar user.email=[email protected] |
然後在 build/filters/filter 裏指明使用這個屬性文件作爲 filtering 屬性值的來源:
<project> ... <build> ... <filters> <filter>project.properties</filter> </filters> ... </build> ... </project> |
Profile 功能
Profile 的作用是允許你在項目文件(pom.xml)裏定義若干個 profile 段,然後在編譯時選擇其中的一個用於覆蓋項目文件原先的定義。接着上一個例子,如果我們需要爲開發環境和生產環境定義不同的 user.name 屬性值,則我們在項目目錄裏創建兩個屬性文件:
profile-development.properties,內容
user.name=foobar |
profile-production.properties,內容
user.name=tom |
然後在項目文件(pom.xml)裏增加 profile 段,如下:
<project> ... <profiles> <profile> <id>development</id> <activation> <activeByDefault>true</activeByDefault> </activation> <build> <filters> <filter>profile-development.properties</filter> </filters> </build> </profile> <profile> <id>production</id> <build> <filters> <filter>profile-production.properties</filter> </filters> </build> </profile> </profiles> </project> |
在編譯項目時,可以使用 -P 參數指定需要使用的 profile 的 id,比如下面命令將會使用 development profile:
$mvn clean compile -Pdevelopment |
如果想使用 production profile 則執行如下命令:
$mvn clean compile -Pproduction |
假如不指定 -P 參數的話,則會使用 activeByDefault=true 的一項(即 development)。
至此,通過 filtering 和 profile 功能實現了爲開發環境和生產環境使用不同配置值的目的。當然 profile 還可以允許你添加更多的定義,比如爲某一個 profile 添加不同的資源文件。在一些大中型項目裏,不同的環境可能僅僅修改配置值並不足夠,可能還需要某個配置文件整個替換,那麼就應該在 profiles/profile/build/resources 段裏指定了。詳細的可以參閱附錄鏈接。