SpringBoot基礎篇配置資訊之多環境配置資訊
前面一篇主要介紹的是如何獲取配置資訊,接下來則是另外一個非常非常基礎和必要的知識點了,應用如何根據不同的環境來選擇對應的配置,即配置的多環境選擇問題
I. 多環境配置
配置區分環境,最直觀的如測試環境和生產環境的DB不同,測試環境的應用要求連線測試DB;生成環境的應用要求連生成DB;對於應用本身來說,業務程式碼啥的都是一樣,無非就是DB的配置不同,如果在程式碼中寫死環境判斷,然後進行選擇配置話,就不太優雅了;
SpringBoot本身就支援多環境配置檔案,應用的配置,除了 application.yml
檔案之外,還會有環境相關的配置,如下一個例項
application.yml application-dev.yml application-pro.yml
1. 多環境選擇
a. 命令規則
配置檔案,一般要求是以 application
開頭,可以是yml檔案也可以是properties檔案
b. 配置選擇
如何確定哪個配置配置檔案(application-dev.yml 與 application-pro.yml)生效呢?
- 通過配置資訊
spring.profile.active
來指定需要載入的配置檔案
通常這個配置資訊會放在 applicatin.yml
檔案中,如下
spring:
profiles:
active: dev
上面這個表示,當前的配置資訊,會從 application.yml
和 application-dev.yml
-dev
檔案中定義的配置資訊,會覆蓋前面的配置資訊
注意
- 上面這個配置的value,可以指定多個配置檔案,用英文逗號分隔
- 其中最右邊的優先順序最高,覆蓋左邊配置檔案中重名的配置資訊
c. 例項演示
配置檔案內容如下
application.yml
# 埠號
server:
port: 8081
spring:
profiles:
active: dev,biz
biz:
total: application
application-dev.yml
biz: env: dev-environment profile: dev-profile
application-pro.yml
biz:
env: pro-environment
profile: pro-profile
application-biz.yml
biz:
whitelist: a,b,c,d,e,f,g
ratelimit: 1,2,3
total: application-biz
profile: biz-profile
通過前面的規則進行分析,當前選中生效的配置檔案為
- application.yml, application-dev.yml, application-biz.yml
- 優先順序為:biz檔案的配置覆蓋dev檔案,dev檔案的覆蓋
application
的配置
程式碼驗證如下
package com.git.hui.boot.properties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
/**
* Created by @author yihui in 09:17 18/9/20.
*/
@SpringBootApplication
public class Application {
public Application(Environment environment) {
String env = environment.getProperty("biz.env");
String whitelist = environment.getProperty("biz.whitelist");
String ratelimit = environment.getProperty("biz.ratelimit");
String total = environment.getProperty("biz.total");
String profile = environment.getProperty("biz.profile");
// application.yml檔案中的配置 spring.profile.active指定具體選中的配置檔案,為 application-dev 和 application-biz
// read from application-dev.yml
System.out.println("env: " + env);
// read from application-biz.yml
System.out.println("whitelist: " + whitelist);
System.out.println("ratelimit: " + ratelimit);
// 當配置檔案 application.yml, application-dev.yml, application-biz.yml 三個檔案都存在時,覆蓋規則為
// biz > dev > application.yml (其中 biz>dev的原則是根據 spring.profile.active 中定義的順序來的,最右邊的優先順序最高)
// read from application-biz.yml
System.out.println("total: " + total);
// read from application-biz.yml
System.out.println("profile: " + profile);
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
輸出結果為
env: dev-environment
whitelist: a,b,c,d,e,f,g
ratelimit: 1,2,3
total: application-biz
profile: biz-profile
2. 優先順序問題
上面雖然看是實現了多環境的配置問題,但看完之後有一個明顯的疑問,選擇環境的配置資訊寫死在application.yml
檔案中,難道說部署到測試和生產環境時,還得記得手動改這個配置的值麼?
如果是這樣的話,也太容易出問題了吧。。。
那麼如何解決這個問題呢,常見的一種方式是通過啟動指令碼,傳入當前環境的引數,來覆蓋選中的環境
a. 配置檔案優先順序
預設的配置檔案是放在 src/main/resources
目錄下,當然也是可以放其他位置的
- 外接,在相對於應用程式執行目錄的
/config
子目錄中 - 外接,在應用程式執行的目錄中
- 內建,放在config包下(即 src/main/resources/config)目錄下
- 內建,放在classpath根目錄下(即預設的 src/main/resources/目錄下)
上面的優先順序是從高到低來的,即外接的改與內建的;config下面的高於根目錄下的
以內建的兩個進行對比,實測結果如下
b. 配置資訊來源
前面一篇中,遺留了一個問題,就是在配置檔案中配置了屬性 user.name = 一灰灰blog
, 但是實際取出的卻是 user
(我個人的電腦使用者名稱),也就是說,Environment中讀取的配置資訊,不僅僅是從配置檔案中獲取,還要其他的一些配置資訊來源
根據優先順序對屬性來源進行排序,如下
- 根目錄下的開發工具全域性設定屬性(當開發工具啟用時為~/.spring-boot-devtools.properties)。
- 測試中的@TestPropertySource註解。
- 測試中的@SpringBootTest#properties註解特性。
- 命令列引數
- SPRING_APPLICATION_JSON中的屬性(環境變數或系統屬性中的內聯JSON嵌入)。
- ServletConfig初始化引數。
- ServletContext初始化引數。
- java:comp/env裡的JNDI屬性
- JVM系統屬性
- 作業系統環境變數
- 隨機生成的帶random.* 字首的屬性(在設定其他屬性時,可以應用他們,比如${random.long})
- 應用程式以外的application.properties或者appliaction.yml檔案
- 打包在應用程式內的application.properties或者appliaction.yml檔案
- 通過@PropertySource標註的屬性源
- 預設屬性(通過SpringApplication.setDefaultProperties指定).
3. 環境選擇的幾種方式
看了上面的配置資訊來源,我們可以如何優雅的實現不同環境選擇不同的配置檔案呢?有下面兩個容易想到和實現的方式了
- 命令列引數
- 應用程式外的配置檔案
a. 命令列引數方式
這種實現思路就是在啟動指令碼中,傳入當前環境,然後覆蓋掉屬性 --spring.profiles.active
,對業務來說,就不需要做任何的改動了,只要啟動指令碼本身區分環境即可,唯一的要求就是遵循統一的規範,一個簡單的實現如下
假定命令列的第一個引數就是環境,取出這個引數,傳入即可
public static void main(String[] args) {
if (args.length > 0) {
SpringApplication.run(Application.class, "--spring.profiles.active=" + args[0] + ",biz");
} else {
SpringApplication.run(Application.class);
}
}
實測結果,注意下面紅框內的pro,覆蓋了配置檔案中的dev
說明
當然可以直接傳入完整的命令列引數--spring.profiles.active=pro,biz
,這樣程式碼內部就不需要進行特殊處理
b. 外接配置檔案方式
當程式以獨立的jar執行時,我個人的感覺是外接的配置檔案是優於內建的配置檔案的;因為修改配置的話,不需要重新打包部署,直接改即可
這種實現方式也沒啥好多說的,相當於把配置檔案拉出來放在外面而已,再根據環境寫具體的spring.profiles.active
的值
II. 小結
- SpringBoot是支援多環境的配置,通過配置屬性
spring.profiles.active
來指定 spring.profiles.active
引數指定多個配置檔案時,右邊的優於左邊的- 應用外的配置檔案優先於應用內,config目錄下的優先於根目錄下的
- 配置引數來源及優先順序可以參看前文: 配置資訊來源
- 命令列引數傳入時,請注意寫法形同
--key=value
III. 其他
0. 專案
1. 一灰灰Blog
一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
2. 宣告
盡信書則不如,已上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
- QQ: 一灰灰/3302797840
3. 掃描關注
一灰灰blog
知識星球