科技新知
Spring Boot 08 - 多情境設置 maven profile 與 application.properties 進階篇
上期我們介紹完最直觀的用法,這期我們再來討論多管齊下的方向。
在開始之前,筆者總結一下上期的 Profile 的要點。
- Spring boot 是經過
spring.profiles.active
去選擇什麼 (spring boot) Profile 生效 spring.profiles.active
它可以在runtime(運行時)動態更改- maven 是經過 xml 去選擇編譯時的 (maven) profile
- maven 編譯時為
spring.profiles.active
填入一個固定值
另外,筆者亦在測試途中,發現一個現像。 maven 並不提供混合 profile,即使下指令同時觸發兩個 profile ,最後亦只有一個 maven profile 生效。但這個部份筆者未在官方文件中找到,大家如果有任何發現,可以幫忙修正。
當我們經IDE編譯時,可以為 spring.profiles.active
填入多個值,各值之間用逗號分隔,就可以觸發多個 profile 。
spring.profiles.active=dev,uat
- 程式碼中的
application.properties
,application-dev.properties
,application-uat.properties
都會生效 - Spring boot會先後載入上述三個檔案,如果有重複值,後面出現的會覆蓋前面的值。
spring.profiles.active
如果填入的值與現在的application-xxx.properties不匹配,該部份不生效,例如
spring.profiles.active=dev,uat
- 程式碼中只有
application.properties
,application-dev.properties
,但沒有application-uat.properties
- Spring boot會先後載入上述兩個檔案
上述的都好理解,當大家都接受上面的結論後,再來看這個現像。
spring.profiles.active
是啟動spring boot時,作為選擇profile的依據。application.properties
可以有一個預設的spring.profiles.active
,正常跑spring boot就會看它。- 正常跑spring boot時,還可以通過傳入參數
--spring.profiles.active=xx
,改變那個值。 - Spring boot test 因為結構特殊,它只會看到
application.properties
中的那個spring.profiles.active
值。 - Spring boot test 暫時沒有方法傳入參數
spring.profiles.active
,但可以經程式碼 @ActiveProfiles 硬改運行中的 profile 。spring.profiles.active
亦只會顯示application.properties
中的那個值。
大家看完概念之後,可以來看看實際例子。
當什麼都不加,就是根據application.properties
的spring.profiles.active
來啟動profile。
mvn clean compile spring-boot:run
# or
mvn clean compile package
java -jar target/spring-boot-profile-0.0.1-SNAPSHOT.jar
正常spring-boot:run的情況下,可以經的 --spring.profiles.active
覆蓋過application.properties
內的值。
mvn clean compile spring-boot:run -Dspring-boot.run.arguments="--spring.profiles.active=dev --spring.profiles.active=uat"
mvn clean compile spring-boot:run -Dspring-boot.run.arguments="--spring.profiles.active=dev,uat"# or
mvn clean compile package
java -jar target/spring-boot-profile-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev --spring.profiles.active=uat
java -jar target/spring-boot-profile-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev,uat
上述例子,若dev,uat內的值沒有衝突,沒有覆蓋問題。但如果有衝突,最後會是uat內定義的值。
因為不是正常spring-boot:run,所以那些參數都沒有用,具體只會看application.properties
內預設spring.profiles.active
mvn clean compile test -Dspring-boot.run.arguments="--spring.profiles.active=dev,uat"# arguments will be ignored, same as
mvn clean compile test
加入Maven之後,就可以修改application.properties
內的預設spring.profiles.active
。但要注意,maven只會有單profile
假設pom.xml如下
application.properties如下
spring.profiles.active=@active.profile@
下述三組例子,有且只有uat生效。因為maven的uat生效後,會修改
mvn clean compile spring-boot:run -Puat
# or
mvn clean compile package -Pdev -Dci=true
java -jar target/spring-boot-profile-0.0.1-SNAPSHOT.jar
# or
mvn clean compile test -Puat
當然,你想要弄一個maven mix profile 也可以
以下例子可以令 dev, uat 同時出現在spring.profiles.active
mvn clean compile spring-boot:run -Pmix
# or
mvn clean compile package -Pmix
java -jar target/spring-boot-profile-0.0.1-SNAPSHOT.jar
# or
mvn clean compile test -Pmix
上述例子都了解後,最後就來看看全部混合的情況
當Test case中沒有硬改 profile 定義,application.properties
中的spring.profiles.active
就直接作用。以下情況就是同時運行dev,uat
// java
@SpringBootTest
class ProfileTests {
}
// bash
mvn clean compile test -Pmix
當Test case中有定義@ActiveProfiles ,application.properties
中的spring.profiles.active
的值會保留,但不在該test case中生效。以下情況就是同時運行uat,dev,但讀取spring.profiles.active的值會是dev,uat。
// java
@SpringBootTest
@ActiveProfiles(value = { "uat", "dev" })
class MultipleProfileUatDevTests {
}
// bash
mvn clean compile test -Pmix
如果我們把maven 指令中的加入package,預期 test 執行的是 uat,dev 。而 jar 的打包結果會是 dev,uat。
// java
@SpringBootTest
@ActiveProfiles(value = { "uat", "dev" })
class MultipleProfileUatDevTests {
}
// bash
mvn clean compile test package -Pmix
但請盡量不要這些做,因為會越來越混亂,特別是打包 prod 環境。為減少出錯的機會,例如test污染了prod的環境,筆者在package時,通常都會跳過test。
mvn clean compile package -Pprod -Dmaven.test.skip=true