每個專案都會有多套執行環境(開發,測試,正式等等),不同的環境配置也不盡相同(如jdbc.url),藉助Jenkins和自動部署提供的便利,我們可以把不同環境的配置檔案單獨抽離出來,打完包後用對應環境的配置檔案替換打包後的檔案,其實maven已經給我們提供了替換方案:profile + filtering
Filtering
Filtering 是 maven 的 resource 外掛 提供的功能,作用是用環境變數、pom檔案裡定義的屬性和指定配置檔案裡的屬性替換屬性(*.properties
)檔案裡的佔位符(${jdbc.url}
),具體使用如下:
在src/main/resources
目錄有個配置檔案jdbc.properties
,內容如下:
jdbc.url=${pom.jdbc.url}
jdbc.username=${pom.jdbc.username}
jdbc.passworkd=${pom.jdbc.password}
配置 resource 外掛,啟用filtering功能並新增屬性到pom:
<project>
...
<!-- 用pom裡定義的屬性做替換 -->
<properties>
<pom.jdbc.url>jdbc:mysql://127.0.0.1:3306/dev</pom.jdbc.url>
<pom.jdbc.username>root</pom.jdbc.username>
<pom.jdbc.password>123456</pom.jdbc.password>
</properties>
<build>
...
<!-- 可以把屬性寫到檔案裡,用屬性檔案裡定義的屬性做替換 -->
<filters>
<filter>src/main/filters.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
...
</project>
編譯包後target
目錄下的jdbc.properties
:
jdbc.url=jdbc:mysql://127.0.0.1:3306/dev
jdbc.username=root
jdbc.passworkd=123456
Profile 簡介
什麼是profile?
<profile>
就像<dependencies>
一樣是pom檔案裡的一個xml元素,在profile裡幾乎可以定義所有在pom裡的定義的內容(<dependencies>
,<properties>
,外掛配置等等,不過不能再定義他自己了)。當一個profile被啟用時,它定義的<dependencies>
,<properties>
等就會覆蓋掉原pom裡定義的相同內容,從而可以通過啟用不同的profile來使用不同的配置。
<!-- profile 的感性認識 -->
<project>
...
<profiles>
<profile>
<id>dev</id>
<properties>
<active.profile>dev</active.profile>
<pom.jdbc.url>jdbc:mysql://127.0.0.1:3306/dev</pom.jdbc.url>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependencies>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
...
</project>
Profile 如何配置
可以在兩個位置配置profile:settings.xml
和 pom.xml
-
settings.xml
裡定義的profile是全域性的,對所有的專案都可用,在裡面定義的配置項也稍微少了些,只能定義遠端伺服器的資訊和屬性資訊(<repositories>
,<pluginRepositories>
,<properties>
)。這些資訊在pom.xml
裡也是可以定義的。 -
pom.xml
裡可以定義的配置如下:
<repositories>
<pluginRepositories>
<dependencies>
<plugins>
<properties>
<modules>
<reporting>
<dependencyManagement>
<distributionManagement>
以及build下的:
<defaultGoal>
<resources>
<testResources>
<finalName>
如果profile被啟用,profile裡的配置和原pom的配置會做覆蓋合併。
如何啟用Profile
可以通過多種方式啟用profile(顯式的,隱式的)
顯式的啟用
通過maven 的-P
引數啟用指定的profile,引數的值是profile的id,多個profile以逗號分割,如果不想啟用某個預設的profile,就在它的id前加個!
mvn -U clean package -Ptest,local,!ignore
IDEA裡則可以在 Maven Projects 裡直接勾選想要啟用的profile
隱式的啟用
配置profile時,可以在 <profile>
的 <activation>
元素下配置隱式啟用的資訊。
預設啟用
-
pom.xml
檔案裡
<!-- 預設啟用 -->
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
-
settings.xml
檔案裡則是通過<activeProfiles>
來配置預設啟用的profile列表
<activeProfiles>
<activeProfile>artifactory</activeProfile>
</activeProfiles>
根據作業系統型別啟用
<profiles>
<profile>
<activation>
<os>
<!-- 不必指定所有資訊 -->
<name>linux</name>
<family>unix</family>
<arch>amd64</arch>
<version>3.19.0-30-generic</version>
</os>
</activation>
</profile>
</profiles>
關於OS值的更多資訊可以參考這裡
根據JDK版本啟用
<!-- 如果jdk的版本為1.8則啟用該profile -->
<profiles>
<profile>
<activation>
<jdk>1.8</jdk>
</activation>
</profile>
</profiles>
也可以通過[1.6,1.8)
匹配多個jdk版本,關於匹配模式的詳細資訊可以參考這裡
根據環境變數啟用
<!-- 如果環境變數裡有`debug`且它的值為`true`則啟用 -->
<!-- 也可以不指定`<value>`元素, 則只有環境變數裡有`debug`就啟用 -->
<profiles>
<profile>
<activation>
<property>
<name>debug</name>
<value>true</value>
</property>
</activation>
</profile>
</profiles>
mvn -U clean package -Ddebug=true
通過判斷檔案是否存在啟用
<profiles>
<profile>
<activation>
<file>
<missing>/path/to/missing/file</missing>
<exists>/path/to/exists/file</exists>
</file>
</activation>
...
</profile>
</profiles>
不同型別的隱式啟用方式可以組合使用,如根據同時指定根據作業系統型別和JDK版本來啟用profile,只有但兩個條件都匹配是才啟用之。
Filtering + Profile
思路:在不同的profile裡配置不同的屬性(properties),然後啟用相應的profile,用其中的屬性去替換jdbc.properties裡的佔位符。
繼續使用介紹Filtering時的例子,現在新增三個profile配置,分別對應開發,測試,正式環境。
修改後的pom檔案如下:
<project>
...
<build>
<filters>
<filter>src/main/filters-${active.profile}.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>dev</id>
<properties>
<active.profile>dev</active.profile>
</properties>
<!-- 把當前profile設定為預設profile,可以同時這是多個為預設-->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<active.profile>test</active.profile>
</properties>
</profile>
<profile>
<id>product</id>
<properties>
<active.profile>product</active.profile>
</properties>
</profile>
...
</project>
然後在src/main
下新建三個檔案:filters-dev.properties
,filters-test.properties
,filters-product.properties
,檔案內容如下(以filters-dev.properties
為例):
pom.jdbc.url=jdbc:mysql://127.0.0.1:3306/dev
pom.jdbc.username=root
pom.jdbc.password=123456
用 dev profile 開啟發包mvn clean package -Pdev
, 打包後jdbc.properties
檔案內容如下:
jdbc.url=jdbc:mysql://127.0.0.1:3306/dev
jdbc.username=root
jdbc.password=123456
如果不同的執行環境只是屬性值的不同,用上面的 profile + filtering
進行下變數替換可以很好的滿足打包需求,如果不是簡單的替換(如log4j.xml,開發環境只要輸出到標準輸出,測試和線上環境則還需要打到檔案且檔案的位置和策略也不相同),這個就需要藉助maven 的 ant 外掛。src/main/resources
目錄下有三個log4j的配置檔案,分別對應三個執行環境:
resources
├── log4j-product.xml
├── log4j-test.xml
└── log4j.xml
配置如下profile:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>config.*.properties</exclude>
<exclude>log4j-*.xml</exclude>
</excludes>
</resource>
</resources>
</build>
</profile>
<profile>
<id>test</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete file="${project.build.outputDirectory}/log4j.xml"/>
<delete file="${project.build.outputDirectory}/log4j-product.xml"/>
<move file="${project.build.outputDirectory}/log4j-test.xml"
tofile="${project.build.outputDirectory}/log4j.xml"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>product</id>
<properties>
<active.profile>product</active.profile>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete file="${project.build.outputDirectory}/log4j.xml"/>
<delete file="${project.build.outputDirectory}/log4j-test.xml"/>
<move file="${project.build.outputDirectory}/log4j-product.xml"
tofile="${project.build.outputDirectory}/log4j.xml"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>