欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot注入自定義的配置文件的方法詳解

 更新時間:2022年09月23日 08:59:47   作者:鴨血粉絲Tang  
在實際的項目開發(fā)過程中,我們經(jīng)常需要將某些變量從代碼里面抽離出來,放在配置文件里面。今天,我們就一起來聊一聊SpringBoot加載配置文件的幾種玩法,需要的可以參考一下

一、簡介

在實際的項目開發(fā)過程中,我們經(jīng)常需要將某些變量從代碼里面抽離出來,放在配置文件里面,以便更加統(tǒng)一、靈活的管理服務配置信息。比如,數(shù)據(jù)庫、eureka、zookeeper、redis、mq、kafka 等服務組件的連接參數(shù)配置,還有我們自定義的項目參數(shù)配置變量。

當然,實際上根據(jù)當前的業(yè)務需求,我們往往會自定義參數(shù),然后注入到代碼里面去,以便靈活使用!

今天,我們就一起來聊一聊SpringBoot加載配置文件的幾種玩法,如果有遺漏,歡迎留言!

SpringBoot 項目在啟用時,首先會默認加載bootstrap.properties或者bootstrap.yml這兩個配置文件(這兩個優(yōu)先級最高);接著會加載application.propertiesapplication.yml;如果何配置了spring.profiles這個變量,同時還會加載對應的application-{profile}.properties或者application-{profile}.yml文件,profile為對應的環(huán)境變量,比如dev,如果沒有配置,則會加載profile=default的配置文件。

雖然說配置項都寫在同一個配置文件沒有問題,但是很多時候我們?nèi)匀幌M芊珠_寫,這樣會比較清晰,比如zookeeper的配置寫在zookeeper.properties,數(shù)據(jù)庫相關(guān)的配置寫在datasource.properties等等,因此就需要設置加載外部配置文件!

具體該如何實現(xiàn)呢,我們一起來看看!

二、代碼實踐

2.1 通過@value注解實現(xiàn)參數(shù)加載

當我們想要在某個類里面注入某個變量,通過@value注解就可以簡單實現(xiàn)參數(shù)的注入!

例如application.properties文件里,配置一個config.name的變量key,值為zhangsan

//參數(shù)定義
config.name=zhangsan

然后在對應的類里面,通過參數(shù)@value注入即可!

@RestController
public?class?HelloController?{
????
????@Value("${config.name}")
????private?String?config;

????@GetMapping("config")
????public?String?config(){
????????return?JSON.toJSONString(config);
????}
}

使用@value注解注入配置,通常情況下有個要求就是,注解里面的變量,必須在application.properties文件里面事先定義好,否則啟動報錯!

當然,如果我們不想讓它抱錯,我們可以給它一個缺省值xxx,比如:

@Value("${config.name:xxx}")
private?String?config;

這樣,SpringBoot 項目在啟用時不會報錯!

2.2 通過@ConfigurationProperties注解實現(xiàn)參數(shù)加載

某些場景下,@value注解并不能滿足我們所有的需求,比如參數(shù)配置的數(shù)據(jù)類型是一個對象或者數(shù)組,這個時候才用@ConfigurationProperties會是一個比較好的選擇!

配置一個對象類型的參數(shù)

例如在application.properties文件里,當我們想配置一個對象類型的參數(shù),我們可以這樣操作!

//參數(shù)定義
config2.name=demo_1
config2.value=demo_value_1

然后,創(chuàng)建一個配置類Config2,用于將定義的變量映射到配置類里面。

@Component
@ConfigurationProperties(prefix?=?"config2")
public?class?Config2?{

????public?String?name;

????public?String?value;

????//...get、set
}

讀取數(shù)據(jù)的方式,也很簡單,直接注入到對應的類里面就可以了

@RestController
public?class?HelloController?{
????
????@Autowired
????private?Config2?config2;

????@GetMapping("config2")
????public?String?config2(){
????????return?JSON.toJSONString(config2);
????}
}

配置一個Map類型的參數(shù)

例如在application.properties文件里,當我們想配置一個 Map 類型的參數(shù),我們可以這樣操作!

//參數(shù)定義
config3.map1.name=demo_id_1_name
config3.map1.value=demo_id_1_value
config3.map2.name=demo_id_2_name
config3.map2.value=demo_id_2_value

然后,創(chuàng)建一個配置類Config3,用于將定義的變量映射到配置類里面。

@Component
@ConfigurationProperties(prefix?=?"config3")
public?class?Config3?{

????private?Map<String,?String>?map1?=?new?HashMap<>();

????private?Map<String,?String>?map2?=?new?HashMap<>();

????//...get、set
}

讀取數(shù)據(jù)的方式,與之類似!

@RestController
public?class?HelloController?{
????
????@Autowired
????private?Config3?config3;

????@GetMapping("config3")
????public?String?config3(){
????????return?JSON.toJSONString(config3);
????}
}

配置一個List類型的參數(shù)

例如在application.properties文件里,當我們想配置一個 List 類型的參數(shù),我們可以這樣操作!

//參數(shù)定義
config4.userList[0].enable=maillist_1_enable
config4.userList[0].name=maillist_1_name
config4.userList[0].value=maillist_1_value

config4.userList[1].enable=maillist_2_enable
config4.userList[1].name=maillist_2_name
config4.userList[1].value=maillist_2_value

config4.userList[2].enable=maillist_3_enable
config4.userList[2].name=maillist_3_name
config4.userList[2].value=maillist_3_value

然后,創(chuàng)建一個配置類Config4,用于將定義的變量映射到配置類里面。

@Component
@ConfigurationProperties(prefix?=?"config4")
public?class?Config4?{

????private?List<UserEntity>?userList;

????public?List<UserEntity>?getUserList()?{
????????return?userList;
????}

????public?void?setUserList(List<UserEntity>?userList)?{
????????this.userList?=?userList;
????}
}
public?class?UserEntity?{

????private?String?enable;
????private?String?name;
????private?String?value;

????//...get、set
}

讀取數(shù)據(jù)的方式,與之類似!

@RestController
public?class?HelloController?{
????
????@Autowired
????private?Config4?config4;

????@GetMapping("config4")
????public?String?config4(){
????????return?JSON.toJSONString(config4);
????}
}

2.3 通過@PropertySource注解實現(xiàn)配置文件加載

正如我們最開始所介紹的,很多時間,我們希望將配置文件分卡寫,比如zookeeper組件對應的服務配置文件是zookeeper.properties,redis組件對應的服務配置文件是redis.properties等等。

這種自定義的配置文件,我們應該如何加載到Spring容器里面呢?

其實方法也很簡單,通過@PropertySource就可以實現(xiàn)!

首先,我們在resources資源文件夾下,創(chuàng)建兩個配置文件test.propertiesbussiness.properties,內(nèi)容如下!

test.properties文件內(nèi)容:

aaa.a1=aa1123
aaa.a2=aa2123
aaa.a3=aa3123
aaa.a4=aa4123

bussiness.properties文件內(nèi)容:

bbbb.a1=bb1123
bbbb.a2=bb2123
bbbb.a3=bb3123
bbbb.a4=bb4123

SpringBoot啟動類上加載配置文件即可!

@SpringBootApplication
@PropertySource(value?=?{"test.properties","bussiness.properties"})
public?class?PropertyApplication?{

????public?static?void?main(String[]?args)?{
????????SpringApplication.run(PropertyApplication.class,?args);
????}
}

讀取數(shù)據(jù)的方式,與之類似!

@RestController
public?class?HelloController?{
????
????@Value("${aaa.a2}")
????private?String?a2;

????@Value("${bbbb.a1}")
????private?String?bbbbA1;
????
????@GetMapping("a2")
????public?String?a2(){
????????return?JSON.toJSONString(a2);
????}

????@GetMapping("bbbbA1")
????public?String?bbbbA1(){
????????return?JSON.toJSONString(bbbbA1);
????}
}

如果我們只是在業(yè)務中需要用到自定義配置文件的值,這樣引入并沒有什么問題;但是如果某些自定義的變量,在項目啟動的時候需要用到,這種方式會存在一些問題,原因如下:

翻譯過來的意思就是說:

雖然在@SpringBootApplication上使用@PropertySource似乎是在環(huán)境中加載自定義資源的一種方便而簡單的方法,但我們不推薦使用它,因為SpringBoot在刷新應用程序上下文之前就準備好了環(huán)境。使用@PropertySource定義的任何鍵都加載得太晚,無法對自動配置產(chǎn)生任何影響。

因此,如果某些參數(shù)是啟動項變量,建議將其定義在application.propertiesapplication.yml文件里面,這樣就不會有問題!

或者,采用【自定義環(huán)境處理類】來實現(xiàn)配置文件的加載!

2.4 通過自定義環(huán)境處理類,實現(xiàn)配置文件的加載

實現(xiàn)方法也很簡單,首先,創(chuàng)建一個實現(xiàn)自EnvironmentPostProcessor接口的類,然后自行加載配置文件。

public?class?MyEnvironmentPostProcessor?implements?EnvironmentPostProcessor?{


????@Override
????public?void?postProcessEnvironment(ConfigurableEnvironment?environment,?SpringApplication?application)?{
????????//自定義配置文件
????????String[]?profiles?=?{
????????????????"test.properties",
????????????????"bussiness.properties",
????????????????"blog.yml"
????????};

????????//循環(huán)添加
????????for?(String?profile?:?profiles)?{
????????????//從classpath路徑下面查找文件
????????????Resource?resource?=?new?ClassPathResource(profile);
????????????//加載成PropertySource對象,并添加到Environment環(huán)境中
????????????environment.getPropertySources().addLast(loadProfiles(resource));
????????}
????}

????//加載單個配置文件
????private?PropertySource<?>?loadProfiles(Resource?resource)?{
????????if?(!resource.exists())?{
????????????throw?new?IllegalArgumentException("資源"?+?resource?+?"不存在");
????????}
????????if(resource.getFilename().contains(".yml")){
????????????return?loadYaml(resource);
????????}?else?{
????????????return?loadProperty(resource);
????????}
????}

????/**
?????*?加載properties格式的配置文件
?????*?@param?resource
?????*?@return
?????*/
????private?PropertySource?loadProperty(Resource?resource){
????????try?{
????????????//從輸入流中加載一個Properties對象
????????????Properties?properties?=?new?Properties();
????????????properties.load(resource.getInputStream());
????????????return?new?PropertiesPropertySource(resource.getFilename(),?properties);
????????}catch?(Exception?ex)?{
????????????throw?new?IllegalStateException("加載配置文件失敗"?+?resource,?ex);
????????}
????}

????/**
?????*?加載yml格式的配置文件
?????*?@param?resource
?????*?@return
?????*/
????private?PropertySource?loadYaml(Resource?resource){
????????try?{
????????????YamlPropertiesFactoryBean?factory?=?new?YamlPropertiesFactoryBean();
????????????factory.setResources(resource);
????????????//從輸入流中加載一個Properties對象
????????????Properties?properties?=?factory.getObject();
????????????return?new?PropertiesPropertySource(resource.getFilename(),?properties);
????????}catch?(Exception?ex)?{
????????????throw?new?IllegalStateException("加載配置文件失敗"?+?resource,?ex);
????????}
????}
}

接著,在resources資源目錄下,我們還需要創(chuàng)建一個文件META-INF/spring.factories,通過spi方式,將自定義環(huán)境處理類加載到Spring處理器里面,當項目啟動時,會自動調(diào)用這個類!

#啟用我們的自定義環(huán)境處理類
org.springframework.boot.env.EnvironmentPostProcessor=com.example.property.env.MyEnvironmentPostProcessor

這種自定義環(huán)境處理類方式,相對會更佳靈活,首先編寫一個通用的配置文件解析類,支持propertiesyml文件的讀取,然后將其注入到Spring容器里面,基本上可以做到一勞永逸!

2.5 最后,我們來介紹一下yml文件讀取

在上文中,我們大部分都是以properties為案例進行介紹,可能有的人已經(jīng)踩過坑了,在項目中使用@PropertySource注解來加載yml文件,結(jié)果啟動直接報錯,原因是@PropertySource不支持直接解析yml文件,只能解析properties文件。

那如果,我想單獨解析yml文件,也不想弄一個【自定義環(huán)境處理類】這種方式來讀取文件,應該如何處理呢?

操作方式也很簡單,以自定義的blog.yml文件為例!

blog.yml文件內(nèi)容:

pzblog:
??name:?helloWorld

然后,創(chuàng)建一個讀取yml文件的配置類

@Configuration
public?class?ConfigYaml?{

????/**
?????*?加載YML格式自定義配置文件
?????*?@return
?????*/
????@Bean
????public?static?PropertySourcesPlaceholderConfigurer?properties()?{
????????PropertySourcesPlaceholderConfigurer?configurer?=?new?PropertySourcesPlaceholderConfigurer();
????????YamlPropertiesFactoryBean?yaml?=?new?YamlPropertiesFactoryBean();
????????yaml.setResources(new?ClassPathResource("blog.yml"));
????????configurer.setProperties(yaml.getObject());
????????return?configurer;
????}
}

讀取數(shù)據(jù)的方式,與之類似!

@RestController
public?class?HelloController?{
????
????@Value("${pzblog.name}")
????private?String?pzblogName;

????@GetMapping("pzblogName")
????public?String?pzblogName(){
????????return?JSON.toJSONString(pzblogName);
????}
}

以上就是SpringBoot注入自定義的配置文件的方法詳解的詳細內(nèi)容,更多關(guān)于SpringBoot注入配置文件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • flowable動態(tài)創(chuàng)建多級流程模板實現(xiàn)demo

    flowable動態(tài)創(chuàng)建多級流程模板實現(xiàn)demo

    這篇文章主要為大家介紹了flowable動態(tài)創(chuàng)建多級流程模板實現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • Java關(guān)鍵字詳解之final static this super的用法

    Java關(guān)鍵字詳解之final static this super的用法

    this用來調(diào)用目前類自身的成員變量,super多用來調(diào)用父類的成員,final多用來定義常量用的,static定義靜態(tài)變量方法用的,靜態(tài)變量方法只能被類本身調(diào)用,下文將詳細介紹,需要的朋友可以參考下
    2021-10-10
  • 深入理解Java的接口與抽象類

    深入理解Java的接口與抽象類

    本文主要介紹java 的接口和抽象類,對接口和抽象類進行介紹對比,深入理解,有需要的小伙伴可以參考下
    2016-07-07
  • JAVA設計模式之責任鏈模式詳解

    JAVA設計模式之責任鏈模式詳解

    這篇文章主要介紹了JAVA設計模式之責任鏈模式詳解,需要的朋友可以參考下
    2015-04-04
  • Spring Boot整合FTPClient線程池的實現(xiàn)示例

    Spring Boot整合FTPClient線程池的實現(xiàn)示例

    這篇文章主要介紹了Spring Boot整合FTPClient線程池的實現(xiàn)示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • Java并發(fā)編程中的volatile關(guān)鍵字詳解

    Java并發(fā)編程中的volatile關(guān)鍵字詳解

    這篇文章主要介紹了Java并發(fā)編程中的volatile關(guān)鍵字詳解,volatile?用于保證我們某個變量的可見性,使其一直存放在主存中,不被移動到某個線程的私有工作內(nèi)存中,需要的朋友可以參考下
    2023-08-08
  • 關(guān)于接口ApplicationContext中的getBean()方法使用

    關(guān)于接口ApplicationContext中的getBean()方法使用

    這篇文章主要介紹了關(guān)于接口ApplicationContext中的getBean()方法使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Java使用備忘錄模式實現(xiàn)過關(guān)類游戲功能詳解

    Java使用備忘錄模式實現(xiàn)過關(guān)類游戲功能詳解

    這篇文章主要介紹了Java使用備忘錄模式實現(xiàn)過關(guān)類游戲功能,結(jié)合實例形式詳細分析了java備忘錄模式的概念、原理及其在過關(guān)類游戲中的具體應用方法,需要的朋友可以參考下
    2018-04-04
  • SpringBoot源碼 PropertySource解析

    SpringBoot源碼 PropertySource解析

    PropertySource是spring中對于鍵值屬性的一種抽象,主要是name和sourcePropertyResolver是對PropertySource提供對外的統(tǒng)一數(shù)據(jù)處理,對于占位符的處理委托于PropertyPlaceholderHelper,對Springboot?源碼 PropertySource相關(guān)知識感興趣的朋友一起看看吧
    2023-01-01
  • Java反射之通過反射獲取一個對象的方法信息(實例代碼)

    Java反射之通過反射獲取一個對象的方法信息(實例代碼)

    下面小編就為大家?guī)硪黄狫ava反射之通過反射獲取一個對象的方法信息(實例代碼)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10

最新評論