1. 程式人生 > 程式設計 >淺談SpringBoot2.4 配置檔案載入機制大變化

淺談SpringBoot2.4 配置檔案載入機制大變化

前言

Spring Boot 2.4.0.M2剛剛釋出,它對 application.properties 和 application.yml 檔案的載入方式進行重構。如果應用程式僅使用單個 application.properties 或 application.yml 作為配置檔案,那麼可能感受不到任何區別。但是如果您的應用程式使用更復雜的配置(例如,Spring Cloud 配置中心等),則需要來了解更改的內容以及原因。

為什麼要進行這些更改

隨著最新版本 Spring Boot 釋出,Spring 一直在努力提升對 Kubernetes 的原生支援。在 Spring Boot 2.3 中,官方增加 Kubernetes Volume 的配置支援,但是未能實現。

Volume 配置掛載是 Kubernetes 的一項常用功能,其中 ConfigMap 指令用於直接在檔案系統上顯示配置。您可以裝載包含多個鍵和值合併的完整 YAML 檔案,也可以使用更簡單的目錄樹格式,其中檔名是鍵,檔案內容是值。

希望同時提供兩者的支援,並且能夠相容我們現有的 application.properties 和 application.yml 。為此需要修改 ConfigFileApplicationListener 類。

ConfigFileApplicationListener 問題

在 Spring Boot 中配置檔案載入類 ConfigFileApplicationListener 屬於比較核心的底層程式碼,每次維護都是非常的困難。並不是因為程式碼編寫錯誤或者缺少相關單元測試,而是在新增新功能時,很難解決之前存在的問題。

即:

  • 配置檔案非常靈活,可以在當前檔案啟用其他配置檔案。
  • 文件載入順序不固定。

以下面的例子來說:

security.user.password: usera
---
spring.profiles: local
security.user.password: userb
runlocal: true
---
spring.profiles: !dev
spring.profiles.include: local
security.user.password: userc

在這裡,我們有一個 多文件 YAML檔案(一個檔案由三個邏輯文件組成,由 --- 分隔)。

如果使用 --spring.profile.actives=prod 執行,那麼 security.user.password 的值是什麼?是否設定 runlocal 屬性?中間部分文件是否包括在內,因為配置檔案在處理時沒有啟用?

我們經常會遇到關於這個檔案處理邏輯的問題,但是每當試圖修復它們時,最後帶來各種各樣的負面問題。

因此,在 Spring boot 2.4 中對 Properties 和 YAML 檔案的載入方式進行兩個重大更改:

  1. 文件將按定義的順序載入。
  2. profiles 啟用開關不能被配置在特定環境中。

文件排序

從 Spring Boot 2.4 開始,載入 Properties 和 YAML 檔案時候會遵循, 在文件中宣告排序靠前的屬性將被靠後的屬性覆蓋 。

這點與 .properties 的排序規則相同。我們可以想一想,每次將一個 Value 放入 Map ,具有相同 key 的新值放入時,將替換已經存在的 Value。

同理對 Multi-document 的 YAML 檔案,較低的排序也將被較高的覆蓋:

test: "value"
---
test: "overridden-value"

Properties 檔案支援多文件屬性

在 Spring Boot 2.4 中, Properties 支援類似 YAML 多文件功能。多文件屬性檔案使用註釋( # )後跟三個(---)破折號來分隔文件( 選擇使用註釋,以使現有的 IDE 正常支援 )。

例如,上面的 YAML 等效的 properties 為:

test=value
#---
test=overridden-value

特定環境啟用配置

上述示例實際上沒有任何意義,在我們開發過程中更為常見是宣告某個屬性僅在特定環境生效啟用。

在 Spring Boot 2.3 中可以配置 spring.profiles 來實現。但在 Spring Boot 2.4 中 屬性更改 為 spring.config.activate.on-profile 。

例如,我們想要 test 屬性僅僅在 dev Profile 啟用時覆蓋它,則可以使用以下配置:

test=value
#---
spring.config.activate.on-profile=dev
test=overridden-value

Profile Activation

使用 spring.profiles.active 屬性在 application.properties 或 application.yaml 檔案的 根配置檔案 來激 相關環境檔案。
例如,下面這樣:

test=value
spring.profiles.active=local
#---
spring.config.activate.on-profile=dev
test=overridden value

不允許的是將 spring.profiles.active 屬性與 spring.config.activate.on-profile 一起使用。例如,以下檔案將引發異常:

test=value
#---
spring.config.activate.on-profile=dev
spring.profiles.active=local # will fail
test=overridden value

通過這一新限制能使 application.properties 和 application.yml 檔案更加容易理解。使得 Spring Boot 本身更易於管理和維護。

Profile Groups

Profile Groups 是 Spring Boot 2.4 中的一項新功能,可讓您將單個配置檔案擴充套件為多個子配置檔案。例如,假設有一組複雜的 @Configuration 類,可以使用 @Profile 註釋有條件地啟用它們。使用 @Profile("proddb") 開啟資料庫配置,使用 @Profile("prodmq") 開啟訊息配置等等。

使用多個配置檔案可以使我們的程式碼更易於理解,但是對於部署而言並不是理想的選擇。若使用者需要同時啟用 proddb , prodmq , prodmetrics 等。那麼 Profile Groups 可讓您做到這一點。

您可以在 application.properties 或 application.yml 檔案中定義 spring.profiles.group,那麼開啟 prod 則就相當於激活了此組的全部環境 。例如:

spring.profiles.group.prod=proddb,prodmq,prodmetrics

Importing 擴充套件 Configuration

現在,我們已經解決了配置檔案處理的基本問題,我們終於能夠考慮我們想要提供的新功能。我們使用 Spring Boot 2.4 提供的主要功能是支援匯入其他配置。

對於早期版本的 Spring Boot,很難在 application.properties 和 application.yml 之外匯入其他 properties 或 yaml 檔案。可以使用 spring.config.additional-location 屬性但它可以處理的檔案型別非常有限。

在 Spring Boot 2.4 可以直接在 application.properties 或 application.yml 檔案中使用新的 spring.config.import 屬性。例如希望匯入一個 "忽略的 git" 的 developer.properties 檔案,以便團隊中的任何開發人員都可以快速更改屬性:

application.name=myapp
spring.config.import=developer.properties

甚至可以將 spring.config.import 與 spring.config.activate.on-profile 結合起來使用。例如,這裡 prod.properties 僅在 prod 配置檔案處於啟用狀態時載入:

spring.config.activate.on-profile=prod
spring.config.import=prod.properties

Import 可以被視為在宣告它們的文件下方插入的其他文件。它們 遵循與常規多文件檔案相同的自上而下的順序:匯入僅被匯入一次,無論聲明瞭多少次。

volume 掛載配置

匯入定義使用與 URL 一樣語法作為其值。如果您的位置沒有字首,則它被視為常規檔案或資料夾。但是,如果您使用 configtree: 字首,則告訴 Spring Boot,您將期望在該位置使用 Kubernetes volume 裝載的配置樹。

例如,您可以在 application.properties 配置:

spring.config.import=configtree:/etc/config

如果您有以下裝載的內容:

etc/
+- config/
+- my/
| +- application
+- test

將在 Spring Environment 中擁有 my.application 和 test 屬性。 my.application 的值是 /etc/config/my/application 的內容, test 的值是 /etc/config/test 的內容。

根據雲平臺型別啟用

如果只希望 Volume 掛載的配置(或該內容的任何屬性)在特 定的雲平臺上 處於啟用狀態,可以使用 spring.config.activate.on-cloud-platform 屬性。它的工作方式與 spring.config.activate.on-profile 類似,但它使用 CloudPlatform 的值,而不是配置檔名稱。

如果我們想要在部署到 Kubernetes 時啟用上述配置樹,我們可以執行以下操作:

spring.config.activate.on-cloud-platform=kubernetes
spring.config.import=configtree:/etc/config

支援其他位置

spring.config.import 屬性中指定的位置字串是完全可插拔的,可以通過編寫幾個自定義類來擴充套件,第三方庫將對自定義位置提供支援。例如,你能想到的第三方 jar 檔案,例如 archaius://… , vault://… 或 zookeeper://… 。

如果您有興趣新增其他位置支援,請檢視 org.springframework.boot.context.config 包 ConfigDataLocationResolver 和 ConfigDataLoader 的 javadoc。

版本回滾

正如上文所描述的,Spring Boot 針對配置檔案的功能變更是非常大的。考慮到低版本的相容性

可以設定 spring.config.use-legacy-processing=true 屬性即可,恢復到之前版本的檔案處理機制。

如果發現關於此處的問題,則需要切換到舊版處理,請 在 GitHub 上提出問題,官方將嘗試解決該問題。

總結

官方希望新的配置資料處理更加好用,並且不會引起太多升級麻煩。如果您想了解更多有關它們的資訊,可以查閱更新的 參考文件。

到此這篇關於淺談SpringBoot2.4 配置檔案載入機制大變化的文章就介紹到這了,更多相關SpringBoot2.4 檔案載入機制內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!