本文只作記錄和參考,希望對自己或者各位路人都有多少價值。
在實際開發過程中,配置信息會因為不同環境而有所不同。而過多的人工干預,會增加工作量和錯誤率。現在記錄的是如何使用maven快速安全地切換配置信息而不需要多餘的人工修改干預。我們就以最常見的數據庫信息切換作為例子。
Project Structure:
------src
| ------ main
| ------java
| ------ 省略,此處不是重點
| ------resources
| ------ db.properties
| ------filters
| ------ db-dev.properties
| ------ db-prod.properties
| ------ test
| ------java
| ------ 省略,此處不是重點
| ------resources
| ------ db.properties
| ------filters
| ------ db-dev.properties
| ------ db-prod.properties
------tags
------target
------trunk
------pom.xml
項目結構就是最常見的maven project 結構。在此,留意filters, 這個是本文的重點。
先來簡述一下。
resources/db.properties -- 程序會從中讀取數據庫信息。對於不同的環境,dev/prod 信息不同。
filters/db-dev.properties -- dev 環境的數據庫信息
filters/db-prod.properties -- prod 環境的數據庫信息
用一句話來概括, 就是字符的替換。 把db.properties的wildcard替換成dev/prod 的相應值。
db.properties 的內容和dev/prod的內容,在格式上是一樣的。
#db.properties db.username=${db.username} db.password=${db.password} application.name=${project.name}
#db-dev
db.username=dev
db.password=dev-pwd
#db-prod
db.username=prod
db.password=prod-pwd
至此,準備工作已經完成。接下來是maven的配置。
${project.basedir}/src/main/filters/db-${env}.properties
src/main/resources
true
解釋一下。
filters 的意義在於,表明使用該文件(s)中定義的值來替換目標字符。(From whom)
resources/resource ,表示替換會對在哪個目錄下的文件作用。 (To whom)
大家可能也會對${env} 有疑問。這個就是動態配置的關鍵之一。"profiles"
在pom.xml 中,有以下聲明:
dev
dev
prod
prod
此處聲明了2個 profiles. 這個profile 其實是可以定義任意的屬性,甚至可以把數據庫的信息定義在上面。不過,這麼做是不推薦的,靈活性太低。相反,僅定義2個profiles, 把並把對應的信息放入相應的properties會使的構建更加靈活和安全。畢竟,這些人手寫錯打錯導致各式各樣的問題屢見不鮮。當這些profile 被激活使用之後,就會初始化一個變量 , env。並且在filter下面的${env}會被替換成真實的值。這樣,就可以動態更改配置。
把pom配置好之後,就可以嘗試編譯,體會一下這個形式的動態配置。
mvn clean compile
此時,會出現以下錯誤:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:2.6:resources
(default-resources) on project mvn.renew: Error loading property file
'D:\TestingDir\mavenBuildDemo\src\main\filters\db-${env}.properties' -> [Help
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
為什麼? 因為這個時候還未有選擇 profile, 所以 ${env} 並沒有被初始化。我們應該用以下命令來構建:
mvn clean compile -Pdev
-P 就是選擇對應在pom中聲明了的profile。
D:\TestingDir\mavenBuildDemo>mvn clean compile -Pdev
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building mvn.renew 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mvn.renew ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mvn.renew ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ mvn.renew ---
[INFO] Compiling 1 source file to D:\TestingDir\mavenBuildDemo\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.482 s
[INFO] Finished at: 2016-04-09T20:52:55+08:00
[INFO] Final Memory: 11M/107M
[INFO] ------------------------------------------------------------------------
構建成功了。那麼怎麼驗證呢 ? 或許大家都知道,compile之後所有文件,包括 class and properties, 都會被放到 target/classes 下面。那麼我們就去target/classes 下面找。我們會找到一個 db.properties文件,打開檢查:
db.username=dev
db.password=dev-pwd
application.name=mvn.renew
成功匹配 !!
但是如果項目很大,每次構建都相當耗時,那麼,有沒有方法只更新配置文件而不重新編譯?
這個問,肯定是有的啦 !
mvn process-resources -Pprod
用process-resources, 這樣,只會更新配置文件,而不會重新編譯項目。
再去看一下properties, 已經變成了 prod 的信息了。
db.username=prod
db.password=prod-pwd
application.name=mvn.renew
本文到此,已經完結。大家有所感受了么?
在自己記錄的時候也喜歡在大家需要的時候給一點啟示或幫助.