SpringBoot中使用configtree讀取樹形文件目錄中的配置詳解
一、介紹
相信絕大多數(shù)使用springboot開發(fā)項目的朋友們在添加配置時,通常都是通過以下幾種方式:
- 在classpath下添加application.yml或application.properties配置文件,或通過spring.config.location指定配置文件位置。
- 通過spring.config.additional-location指定額外的配置文件位置。
- 通過spring.config.import導(dǎo)入指定位置的配置文件。
但無論通過哪種方式,其配置的形式都是通過在配置文件中通過key - value的形式添加具體配置的,且配置文件類型為yaml或properties。如下所示:
properties文件內(nèi)容示例
key1 = value1
yaml文件內(nèi)容示例
key1: value1
其中key1作為配置名,value1作為配置值。
今天給大家介紹另一種配置形式,該配置使用文件名作為配置名,文件內(nèi)容作為配置值。
如文件名為username的內(nèi)容如下:
admin
文件名為password的內(nèi)容如下:
123456
二、演示環(huán)境
本演示項目的環(huán)境如下:
- java:1.8
- springboot:2.4.3
三、項目演示
本項目演示的是,在指定目錄中添加配置文件,并以文件名為key,文件內(nèi)容為value;然后在application.yml配置文件中通過spring.config.import指定configtree將目錄中的所有配置文件添加到項目的環(huán)境中,并通過placeholder${}的形式獲取配置。
1. 配置文件
我們在本地文件系統(tǒng)中添加配置文件,其目錄結(jié)構(gòu)如下所示
/
etc/
app/
config/
admin/
username
password
db/
username
password
nacos/
username
password各個配置文件內(nèi)容如下所示
/etc/app/config/admin/username
admin
/etc/app/config/admin/password
123456
/etc/app/config/db/username
mysql
/etc/app/config/db/password
123456
/etc/app/config/nacos/username
nacos
/etc/app/config/nacos/password
nacos
2. 導(dǎo)入配置
在application.yml配置文件中添加配置spring.config.import。
注意,當我們要添加以文件名為key,文件內(nèi)容為value的配置文件時,必須在路徑前添加前綴configtree:,且路徑最后以/結(jié)尾。
另外,該路徑支持*通配符。
spring:
config:
import:
- configtree:/etc/app/config/如上所示,springboot將讀取路徑/etc/app/config/(包括子目錄)中的所有文件,并以文件名為key,文件內(nèi)容為value。
3. 檢測配置屬性
當我們按照上面示例配置時,由于在application.yml中配置的spring.config.import目錄為/etc/app/config/,因此我們可以通過admin.username、admin.password、db.username、db.password、nacos.username和nacos.password獲取對應(yīng)文件內(nèi)容的值。
下面我們啟動項目對其進行檢驗。
啟動項目:

輸出:

四、應(yīng)用場景
看到這里,想必很多小伙伴雖然知道springboot如何通過spring.config.import + configtree來讀取以文件名為key,文件內(nèi)容為value的配置,但是這種配置方式使用起來并不方便,且一個文件僅對應(yīng)一個配置屬性,那如果需要大量配置豈不是要創(chuàng)建大量文件?
其實,使用該配置方式和使用application.yml方式應(yīng)該是相輔相成的,兩者應(yīng)當配合使用。
當我們在云平臺(比如docker)上運行應(yīng)用程序時,有時需要讀取容器提供的配置值。而我們多數(shù)情況下都是通過該容器的環(huán)境變量來獲取所需的配置,但是如果我們可能會頻繁修改該環(huán)境變量或該變量需要加密時,就可能暴露出它的缺點了。因為容器的環(huán)境變量是在創(chuàng)建鏡像的時候就確定的,當我們需要修改該環(huán)境變量時就意味著已經(jīng)創(chuàng)建的容器需要刪除了。
所以我們可以通過容器掛載卷的方式,將該環(huán)境變量保存在文件中,通過掛載卷將配置文件掛載到容器中。
五、源碼解析
springboot通過ConfigTreeConfigDataLocationResolver和StandardConfigDataLocationResolver兩種配置文件位置解析器來解析配置文件的位置,然后通過ConfigTreeConfigDataLoader和StandardConfigDataLoader來加載對應(yīng)配置文件中的配置內(nèi)容。
因此結(jié)合本文重點,我們應(yīng)主要關(guān)注ConfigTreeConfigDataLocationResolver和ConfigTreeConfigDataLoader是如何解析配置文件的位置并從文件中讀取配置內(nèi)容的。
1. ConfigTreeConfigDataLocationResolver
首先我們查看ConfigTreeConfigDataLocationResolver是如何解析出配置文件目錄的,主要分兩步:①判斷配置的路徑是否滿足解析的條件,②解析配置文件的位置。
判斷配置的路徑是否滿足解析的條件
該判斷邏輯通過isResolvable()方法完成,主要判斷依據(jù)就是配置的spring.config.import值是否包含configtree:前綴,如果包含,則滿足條件。
private static final String PREFIX = "configtree:";
@Override
public boolean isResolvable(ConfigDataLocationResolverContext context, ConfigDataLocation location) {
return location.hasPrefix(PREFIX);
}解析配置文件的位置
該邏輯通過方法resolve()完成,其目的是根據(jù)配置的spring.config.import目錄轉(zhuǎn)換為該目錄下文件的資源。
@Override
public List<ConfigTreeConfigDataResource> resolve(ConfigDataLocationResolverContext context,
ConfigDataLocation location) {
try {
return resolve(context, location.getNonPrefixedValue(PREFIX));
}
catch (IOException ex) {
throw new ConfigDataLocationNotFoundException(location, ex);
}
}
private List<ConfigTreeConfigDataResource> resolve(ConfigDataLocationResolverContext context, String location)
throws IOException {
// 目錄必須以“/結(jié)尾”
Assert.isTrue(location.endsWith("/"),
() -> String.format("Config tree location '%s' must end with '/'", location));
// 如果目錄不是通配符的形式,則直接根據(jù)該目錄獲取該目錄下文件的資源集合。
if (!this.resourceLoader.isPattern(location)) {
return Collections.singletonList(new ConfigTreeConfigDataResource(location));
}
// 如果目錄是通配符的形式,則對其進一步處理,獲取該目錄下文件的資源集合。
Resource[] resources = this.resourceLoader.getResources(location, ResourceType.DIRECTORY);
List<ConfigTreeConfigDataResource> resolved = new ArrayList<>(resources.length);
for (Resource resource : resources) {
resolved.add(new ConfigTreeConfigDataResource(resource.getFile().toPath()));
}
return resolved;
}2. ConfigTreeConfigDataLoader
然后我們分析ConfigTreeConfigDataLoader是如何根據(jù)配置文件資源加載其內(nèi)容的。

在加載配置屬性中,我們看到該方法主要分兩步
①根據(jù)文件資源獲取文件路徑path
②根據(jù)文件路徑獲取該文件中的配置。我們在方法結(jié)束時添加斷點,然后啟動項目,讓代碼運行到斷點處。如下圖所示,我們發(fā)現(xiàn)springboot已經(jīng)按照預(yù)期將各個配置文件讀取成功了。

任意點擊其中一個元素,可以看到配置文件中的內(nèi)容也已經(jīng)被加載了

最后將其封裝到ConfigData對象中返回。
六、總結(jié)
- 通過spring.config.import + configtree:前綴的方式,加載以文件名為key、文件內(nèi)容為value的配置屬性。
- configtree:應(yīng)以/結(jié)尾。
- 適用于代替在云平臺中讀取加密的系統(tǒng)環(huán)境變量的場景。
到此這篇關(guān)于SpringBoot中使用configtree讀取樹形文件目錄中的配置詳解的文章就介紹到這了,更多相關(guān)SpringBoot讀取文件目錄配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于JAVA文件中獲取路徑及WEB應(yīng)用程序獲取路徑的方法
下面小編就為大家?guī)硪黄贘AVA文件中獲取路徑及WEB應(yīng)用程序獲取路徑的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
SpringBoot使用Filters實現(xiàn)請求過濾和預(yù)處理
過濾器(Filter)是一種在Web應(yīng)用中用于攔截和處理HTTP請求和響應(yīng)的對象,在Java Web開發(fā)中,過濾器是實現(xiàn)特定功能,如認證、日志記錄和字符編碼處理的重要工具,本文主要介紹了SpringBoot使用Filters實現(xiàn)請求過濾和預(yù)處理,需要的朋友可以參考下2024-08-08
Java guava monitor監(jiān)視器線程的使用詳解
工作中的場景中是否存在類似這樣的場景,需要提交的線程在某個觸發(fā)條件下執(zhí)行。本文主要就是使用guava中的monitor來優(yōu)雅的實現(xiàn)帶監(jiān)視器的線程2021-11-11
解決java.lang.IllegalArgumentException異常問題
這篇文章主要介紹了解決java.lang.IllegalArgumentException異常問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
基于spring cloud多個消費端重復(fù)定義feign client的問題
這篇文章主要介紹了spring cloud多個消費端重復(fù)定義feign client的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Mybatis不啟動項目直接測試Mapper的實現(xiàn)方法
在項目開發(fā)中,測試單個Mybatis Mapper方法通常需要啟動整個SpringBoot項目,消耗大量時間,本文介紹通過Main方法和Mybatis配置類,快速測試Mapper功能,無需啟動整個項目,這方法使用AnnotationConfigApplicationContext容器2024-09-09

