成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺談SpringBoot加載配置文件的實現方式,通俗易懂!

開發 架構
今天,我們就一起來聊一聊SpringBoot加載配置文件的幾種玩法!

一、簡介

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

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

今天,我們就一起來聊一聊SpringBoot加載配置文件的幾種玩法!

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

雖然說配置項都寫在同一個配置文件沒有問題,但是很多時候我們仍然希望能分開寫,這樣會比較清晰,比如zookeeper的配置寫在zookeeper.properties,數據庫相關的配置寫在datasource.properties等等,因此就需要設置加載外部配置文件!

具體該如何實現呢,我們一起來看看!

二、代碼實踐

2.1、通過@value注解實現參數加載

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

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

//參數定義
config.name=zhangsan

然后在對應的類里面,通過參數@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注解實現參數加載

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

  • 配置一個對象類型的參數

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

//參數定義
config2.name=demo_1
config2.value=demo_value_1

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

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

public String name;

public String value;

//...get、set
}

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

@RestController
public class HelloController {

@Autowired
private Config2 config2;

@GetMapping("config2")
public String config2(){
return JSON.toJSONString(config2);
}
}
  • 配置一個Map類型的參數

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

//參數定義
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

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

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

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

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

//...get、set
}

讀取數據的方式,與之類似!

@RestController
public class HelloController {

@Autowired
private Config3 config3;

@GetMapping("config3")
public String config3(){
return JSON.toJSONString(config3);
}
}
  • 配置一個List類型的參數

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

//參數定義
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

然后,創建一個配置類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
}

讀取數據的方式,與之類似!

@RestController
public class HelloController {

@Autowired
private Config4 config4;

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

2.3、通過@PropertySource注解實現配置文件加載

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

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

其實方法也很簡單,通過@PropertySource就可以實現!

首先,我們在resources資源文件夾下,創建兩個配置文件test.properties和bussiness.properties,內容如下!

test.properties文件內容:

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

bussiness.properties文件內容:

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);
}
}

讀取數據的方式,與之類似!

@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);
}
}

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

翻譯過來的意思就是說:

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

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

或者,采用【自定義環境處理類】來實現配置文件的加載!

2.4、通過自定義環境處理類,實現配置文件的加載

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

public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {


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

//循環添加
for (String profile : profiles) {
//從classpath路徑下面查找文件
Resource resource = new ClassPathResource(profile);
//加載成PropertySource對象,并添加到Environment環境中
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資源目錄下,我們還需要創建一個文件META-INF/spring.factories,通過spi方式,將自定義環境處理類加載到Spring處理器里面,當項目啟動時,會自動調用這個類!

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

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

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

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

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

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

blog.yml文件內容:

pzblog:
name: helloWorld

然后,創建一個讀取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;
}
}

讀取數據的方式,與之類似!

@RestController
public class HelloController {

@Value("${pzblog.name}")
private String pzblogName;

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

三、小結

本文主要圍繞 SpringBoot 加載配置文件的幾種實現方式,做了一次內容總結,如果有遺漏的地方,歡迎網友批評指出!

四、參考

1、springBoot 官方文檔

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2011-10-26 19:57:33

2019-06-19 08:30:47

網絡協議IPTCP

2023-01-06 09:40:20

項目性能

2020-06-08 10:50:58

前端TypeScript代碼

2021-05-26 16:12:20

區塊鏈加密貨幣比特幣

2022-06-28 07:31:11

哨兵模式redis

2022-09-23 08:32:53

微服務架構服務

2023-09-02 21:14:32

2021-11-04 08:16:50

MySQL SQL 語句數據庫

2022-07-06 08:17:50

C 語言函數選型

2019-05-20 07:37:00

TCPIP網絡協議

2018-01-17 22:36:46

區塊鏈數字貨幣比特幣

2021-05-30 19:02:59

變量對象上下文

2021-05-25 09:50:01

GitLinux命令

2018-03-11 15:11:38

物聯網數據物聯網數據

2018-03-05 08:35:12

物聯網互聯網網絡技術

2021-05-13 13:20:00

Git命令Linux

2018-03-29 06:40:26

物聯網

2018-03-11 14:57:07

物聯網組網無線通信

2018-01-18 17:14:58

分布式文件系統FastDFS
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一区二区三区日本 | 中文字幕在线一区二区三区 | 中文字幕亚洲精品 | 午夜影院官网 | 欧美激情精品久久久久久 | 99久久婷婷国产综合精品电影 | 91视频麻豆| 国产一在线观看 | 伊人伊成久久人综合网站 | www视频在线观看 | 精品国产黄a∨片高清在线 成人区精品一区二区婷婷 日本一区二区视频 | 欧美mv日韩mv国产网站91进入 | 国产精品久久久久久久 | 中文字幕在线视频网站 | 午夜视频一区二区 | 一区二区高清在线观看 | 一区二区三区视频在线免费观看 | 天堂资源视频 | 在线观看亚洲一区二区 | 日本免费在线看 | 欧美一区二区免费视频 | 超碰在线久 | 伊人久麻豆社区 | 日韩欧美操 | 99re在线 | 九九热国产精品视频 | 久久婷婷av | 综合一区二区三区 | 欧美一级视频在线观看 | 又黑又粗又长的欧美一区 | 亚洲精品久久久久久久久久久久久 | 日日夜夜狠狠操 | 亚洲欧美日韩在线不卡 | 欧产日产国产精品v | 一级黄色片美国 | 99精品久久99久久久久 | 天堂色 | 黄色大片在线免费观看 | 巨大荫蒂视频欧美另类大 | 成人中文字幕在线 | 精品国产乱码久久久久久中文 |