Maven Profile 與 Spring Profile 管理多環境打包
一般開發團隊會有多個部署環境,如 dev 環境用於開發自測,QA 環境讓測試團隊測試, Production 環境作為線上環境。通常不同環境的配置不同,我們希望打包時的人力消耗最少。
#Spring Boot Profile
Spring Boot Profile 有許多的功能,這裡只說管理配置的內容。Spring 載入配置的順序如下:
- Jar 包外的
application-{profile}.properties
- Jar 包內的
application-{profile}.properties
- Jar 包外的
application.properties
- Jar 包內的
application.properties
例如,如果我們在 application.properties
中指定
spring.profiles.active = dev |
則 spring 會使用 application-dev.properties
檔案中的配置來覆蓋
application.properties
檔案中的相應配置。
#Maven Profile
如果用的不是 Spring 要怎麼管理多個 Profile 呢?可以從構建工具 Maven 下手。
Maven 也提供了 Profile 支援,它允許我們在 pom.xml
中定義多個 Profile ,每個
profile 可以指定自己的一些配置、依賴、觸發條件等。例如:
<profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <profile.active>dev</profile.active> </properties> </profile |
上面指定了兩個 profile: dev
和 prod
,其中 dev
是預設啟用的,當profile 被啟用時,它定義的的屬性、依賴等內容就會起效。這裡我們定義了profile.active
屬性,之後會用到。
在編譯時指定 mvn clean install -Pprod
就能切換成 prod
profile。
#多環境打包的具體步驟
Maven 與 Spring Profile 的功能是有重合的,只使用一種其實就能實現多環境多配置。但它們各有千秋:
- Spring profile 除了指定配置,還有一些其它作用(如為不同的 profile 生成不同的 bean),但每次打包前都需要手工指定啟用哪個 profile
- Maven Profile 可以通過命令列指定使用的 profile,但缺少了 spring profile 的一些特定功能。
因此我們希望融合二者,取長補短。步驟如下:
#在 pom.xml 中定義 Profile
這裡跟上面介紹的一樣,定義兩個/多個 profile 併為各個 profile 指定自己的屬性:
<profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <profile.active>dev</profile.active> </properties> </profile> <profile> <id>prod</id> <properties> <profile.active>prod</profile.active> </properties> </profile></profiles> |
#在 pom.xml 中定義資源過濾
目的是為了讓 maven 在構建時用 profile 中指定的屬性來替換
application.properties
中的內容。
<resources> <resource> <directory>src/main/resources</directory> <!--①--> <excludes> <exclude>application*.properties</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <!--②--> <filtering>true</filtering> <includes> <include>application.properties</include> <include>application-${profile.active}.properties</include> </includes> </resource></resources> |
①中,我們通過 excludes
來將所有的 application*.properties
排除在外,這樣
maven 在打包時就不會複製這些檔案。畢竟我們不希望把
application-dev.properties
也包含在 prod 的 jar 包裡。
②中,通過開啟 filtering
,maven 會將檔案中的 @[email protected]
替換 profile 中定義的
XX
變數/屬性。另外,我們還通過 includes
來告訴 maven 根據profile 來複制對應的 properties
檔案。
#用 Maven 變數指定 Spring Profile
在 application.properties
檔案中加入下面這行:
spring.profiles.active = @[email protected] |
這裡 profile.active
是在 maven profile 中的 properties
定義的,而 @[email protected]
的語法則是上節提到的 maven filtering 替換變數的語法。
#構建不同的包
mvn clean package -P<profile_name> |
#與 Intellij IDEA 整合
IDEA 在 Build 時並不會處理 Maven Profile 的 filtering 設定,在 Run 的時候會直接複製 application.properties
檔案到 target/class
目錄下,而由於檔案中包含
@[email protected]
(沒有被 maven 替換)且 @
是非法字元,因此沒有辦法執行。
解決方法是讓 IDEA Run 之前執行 mvn resources:resouces
,如下圖:
#小結
Maven profile 與 Spring profile 有自的優點,結合起來的步驟如下:
- 在
pom.xml
中定義多個 profile 及自己的屬性 - 在
pom.xml
中定義 resource filtering,一方面控制 jar 中包含的資原始檔,一方面允許@[email protected]
的變數替換 - 在
application.properties
中指定spring.profiles.active
,值為 maven profile 中定義的屬性。 - 構建時使用
mvm clean package -P<profile>
來指定 profile。