大型項目中,分開發環境、測試環境、生產環境等;html
不一樣環境,配置不一樣,或數據源,或服務器,或數據庫等;mysql
問題來了,如何使用Maven針對不一樣的環境來打包呢?git
Maven提供了Profile的概念,用來解決此類問題,其原理很簡單,就是使用變量替換;舉個例子來講明,測試項目目錄結構以下圖所示:github
好比開發環境和生產環境的數據庫不一樣,db.properties配置文件內容以下:sql
- #測試庫
- db.url=192.10.2.168
- db.username=dbtest
- db.password=dbtest
- #正式庫
- #db.url=192.20.1.11
- #db.username=admin
- #db.password=comfreesecurity
默認開啓測試環境;生產環境打包時,須要手動修改該配置文件.juvenxu說過,手動意味着低效率,高錯誤率!!shell
Maven提供的Profile功能,可解決以上問題:數據庫
一、在pom.xml文件中定義兩個不一樣的Profile,分別定義開發環境和生產環境的數據庫信息:apache
- <profiles>
- <profile>
- <id>kaifa</id>
- <properties>
- <db.url>192.10.2.168</db.url>
- <db.username>dbtest</db.username>
- <db.password>dbtest</db.password>
- </properties>
- </profile>
-
- <profile>
- <id>shengchan</id>
- <properties>
- <db.url>192.20.1.11</db.url>
- <db.username>admin</db.username>
- <db.password>comfreesecurity</db.password>
- </properties>
- </profile>
- </profiles>
二、將原來的配置文件內容修改以下:服務器
- db.url=${db.url}
- db.username=${db.username}
- db.password=${db.password}
三、須要開啓資源文件過濾,代碼以下:app
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- </resources> 添加<filtering>true</filtering>,容許使用變量替換資源文件;
四、使用Maven命令打包時,指定Profile進行打包,命令以下:
mvn package -Pkaifa
mvn package -Pshengchan
如此便可。
此命令用的多了,就會發現,兩個環境必選其一,若是能設置其一個爲默認開啓,就不用每次都手動指定了,這個需求很現實,畢竟開發環境須要持續不斷的編譯、打包、部署等,而上線,則是一段時間纔會運行一次的;所以,默認啓用開發環境是最優的方案,Maven支持默認啓用某個Profile,只需在<profile>內添加以下代碼便可:
- <activation>
- <activeByDefault>true</activeByDefault>
- </activation>
此處須要注意:一旦顯式指定某個Profile,則該配置無效!
在實際開發中使用以上方式操做時,天然而然的會提出如下的問題:假如配置文件的信息不少,那麼Profile的內容會很臃腫,不便於管理,若是能將配置信息從Profile抽取出來,獨立放置,再根據不一樣的Profile去調用,如此就更好了!
Maven針對以上需求,確實有解決方案,就是使用<filters>標籤,針對不一樣的環境,使用不一樣的文件替換原來配置文件中的變量。
項目根目錄下新建以下目錄和文件:
db.properties問標準的屬性文件,kaifa/db.properties和shengchan/db.properties文件內容分別以下:
- db.url=192.10.2.168
- db.username=dbtest
- db.password=dbtest
- db.url=192.20.1.11
- db.username=admin
- db.password=confreesecurity
將Profile中的屬性信息抽取到了db.properties文件中,同時在Profile中添加<filters></filters>部分,修改後的代碼以下:
- <profiles>
- <profile>
- <id>kaifa</id>
- <activation>
- <activeByDefault>true</activeByDefault>
- </activation>
- <build>
- <filters>
- <filter>${basedir}/filters/kaifa/db.properties</filter>
- </filters>
- </build>
- </profile>
-
- <profile>
- <id>shengchan</id>
- <build>
- <filters>
- <filter>${basedir}/filters/shengchan/db.properties</filter>
- </filters>
- </build>
- </profile>
- </profiles>
添加了<filters><filter>...</filter></filters>部分,使用指定的文件內容替換原文件中的變量;
如此以後,使用Maven命令進行構建便可。
細心的人會發現,以上Profile中的filters部分,除了使用的目錄名稱不一樣以外,其餘代碼所有相同,重複!!!
若是再多幾個環境的話,代碼冗餘可想而知,所以須要優化,其實方法很簡單,仍是使用變量替換,修改後的pom.xml文件內容以下:
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>com.test</groupId>
- <artifactId>Profile</artifactId>
- <version>0.0.1-SNAPSHOT</version>
-
- <build>
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- </resources>
- <filters>
- <filter>${basedir}/filters/${filters.env}/db.properties</filter>
- </filters>
- </build>
- <profiles>
- <profile>
- <id>kaifa</id>
- <activation>
- <activeByDefault>true</activeByDefault>
- </activation>
- <properties>
- <filters.env>kaifa</filters.env>
- </properties>
- </profile>
-
- <profile>
- <id>shengchan</id>
- <properties>
- <filters.env>shengchan</filters.env>
- </properties>
- </profile>
- </profiles>
- </project>
使用-P參數時,會激活<filters.env>屬性,從而使用指定的過濾文件進行變量替換。
其實,以上方式使用久了,仍是會有些想法,既然用變量,也就是說,必須使用Maven命令以後,才能部署到Tomcat等服務器中,屢次重複的操做,仍是有至關多的時間浪費在maven命令上,尤爲在改動不多的代碼的狀況下;
此時又會提出新的需求,可否在不使用maven命令的狀況下便可進行平常開發;測試環境(或生產環境)打包時,使用Maven命令和-P參數指定環境進行打包呢?
很幸運,Juven Xu--國內Maven第一人--爲咱們提供了這樣的一個插件portable-config-maven-plugin,使用該插件,能夠在不改變原有代碼的基礎上,進行不一樣環境的打包。
------如下應該算做最佳實踐了
portable-config-maven-plugin插件的原理是內容替換(而不是變量替換);
插件代碼地址:https://github.com/juven/portable-config-maven-plugin,目前最新版本爲1.1.4;
該插件使用方法以下:
假設src/main/resources/db.properties文件代碼以下:
- database.jdbc.username=dev
- database.jdbc.password=dev_pwd
對於測試環境,建立一個屬性替換文件src/main/portable/test.xml,代碼以下:
- <?xml version="1.0" encoding="utf-8" ?>
- <portable-config>
- <config-file path="WEB-INF/classes/db.properties">
- <replace key="database.jdbc.username">test</replace>
- <replace key="database.jdbc.password">test_pwd</replace>
- </config-file>
- </portable-config>
此文件爲替換內容描述文件,<config-file>標籤的path屬性的值是基於war包的
相對路徑
,指須要被內容替換的文件;
配置portable-config-maven-plugin插件(
該插件默認綁定到package聲明週期
):
- <plugin>
- <groupId>com.juvenxu.portable-config-maven-plugin</groupId>
- <artifactId>portable-config-maven-plugin</artifactId>
- <version>1.1.4</version>
- <executions>
- <execution>
- <goals>
- <goal>replace-package</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <portableConfig>src/main/portable/test.xml</portableConfig>
- </configuration>
- </plugin>
或在命令行指定替換內容描述文件:mvn clean package -DportableConfig="src/main/portable/test.xml"
打包完成後,db.properties文件內容會被替換。
該插件目前支持的內容替換文件格式有:
.properties
- database.jdbc.username=dev
- database.jdbc.password=dev_pwd
- 使用
- <replace key="database.jdbc.username">test</replace>
- <replace key="database.jdbc.password">test_pwd</replace>
- 替換爲:
- database.jdbc.username=test
- database.jdbc.password=test_pwd
.xml(xml元素和屬性可使用xPath進行替換)
- <?xml version="1.0" encoding="UTF-8"?>
- <server>
- <port>8080</port>
- <hosts>
- <host id="1">localhost</host>
- <host id="2">localhost</host>
- </hosts>
- <mode value="debug" />
- </server>
- 使用
- <replace xpath="/server/port">80</replace>
- <replace xpath="//host/[@id='1']">192.168.1.1</replace>
- <replace xpath="//host/[@id='2']">192.168.1.2</replace>
- <replace xpath="/server/mode/@value">run</replace>
- 替換爲:
- <?xml version="1.0" encoding="UTF-8"?>
- <server>
- <port>80</port>
- <hosts>
- <host id="1">192.168.1.1</host>
- <host id="2">192.168.1.2</host>
- </hosts>
- <mode value="run"/>
- </server>
.sh
- 無引號、單引號、雙引號、輸出的shell變量可被替換
- BIN_HOME=/tmp/bin
- OUT_HOME="/tmp/out"
- LOG_HOME='/tmp/log'
- export APP_HOME="/tmp/app"
- 使用
- <replace key="BIN_HOME">/home/juven/bin</replace>
- <replace key="OUT_HOME">/home/juven/out</replace>
- <replace key="LOG_HOME">/home/juven/log</replace>
- <replace key="APP_HOME">/home/juven/app</replace>
- 替換爲:
- BIN_HOME=/home/juven/bin
- OUT_HOME="/home/juven/out"
- LOG_HOME='/home/juven/log'
- export APP_HOME="/home/juven/app"
相似.properties格式
- 假若有個key=value類型的配置文件,但擴展名不是.properties,可按照如下方式指定:
- <?xml version="1.0" encoding="utf-8" ?>
- <portable-config>
- <config-file path="db.ini" type=".properties">
- <replace key="mysql.host">192.168.1.100</replace>
- </config-file>
- </portable-config>
- 使用type屬性強制指定文件類型。
對該插件的介紹到此爲止。
回頭看看,發現內容和標題不符,說是介紹portable-config-maven-plugin插件,
卻花了大篇幅的內容介紹了Maven其餘的標籤使用,不過以上內容總有相同之處--針對不一樣環境打包的一些解決方法。