天天看點

Spring Boot 2.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 上提出問題

,官方将嘗試解決該問題。

總結

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

參考文檔

歡迎關注我,後續會通過代碼來詳細說明此處變更。

翻譯: 冷冷、如夢技術

原文連結:

https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4
項目推薦: Spring Cloud 、Spring Security OAuth2的RBAC權限管理系統 歡迎關注