SpringBoot配置載入,各配置檔案優先順序對比
文章內容:
- SpringBoot配置檔案的基本使用;
- yaml配置檔案優先順序問題講解;
- yaml配置檔案目錄及比較說明;
- 自定義配置屬性;
- @ConfigurationProperties與@Value兩種註解對比;
- idea自定義yaml配置提示
- 載入外部配置;
- 裝配配置檔案(properties,yaml);
- 引入xml配置檔案。
1.SpringBoot配置檔案
SpringBoot使用一個以application命名的配置檔案作為預設的全域性配置檔案。支援properties字尾結尾的配置檔案或者以yml/yaml字尾結尾的YAML的檔案配置。
以設定應用埠為例
properties檔案示例(application.properties):
server.port=80
YAML檔案示例(application.yml):
server:
port: 80
兩者同時存在情況
假如各配置檔案都配置了不同的埠,那麼SpringBoot會使用哪一個埠呢?帶著疑問試驗一下例項
- 在resources目錄下建立兩個配置檔案,一個為application.yml配置檔案,設定埠為8010,另一個為application.properties配置檔案,設定埠為8010;
- 重啟系統;
- 執行結果:
- 結論:可見在同一目錄下,properties配置優先順序 > YAML配置優先順序。//所以我們在jar包啟動時帶上properties寫法的配置可以覆蓋配置
2.配置檔案目錄
SpringBoot配置檔案可以放置在多種路徑下,不同路徑下的配置優先順序有所不同。
可放置目錄(優先順序從高到低)
- file:./config/ (當前專案路徑config目錄下);
- file:./ (當前專案路徑下);
- classpath:/config/ (類路徑config目錄下);
- classpath:/ (類路徑config下).
優先順序由高到底,高優先順序的配置會覆蓋低優先順序的配置;
SpringBoot會從這四個位置全部載入配置檔案並互補配置;
我們可以從ConfigFileApplicationListener這類便可看出,其中DEFAULT_SEARCH_LOCATIONS
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
接著getSearchLocations方法中去逗號解析成Set,其中內部類Loader負責這一配置檔案的載入過程,包括載入profile指定環境的配置,以application+’-’+name格式的拼接載入。
多種目錄配置同時存在情況
接下來還是以埠配置為例
- 在resources/config目錄下配置檔案設定埠為8010;
- 在resources/目錄下配置檔案設定埠為8020;
- 在類路徑config目錄下配置檔案設定埠為8030;
- 在類路徑下配置檔案設定埠為8040;
最終執行結果:
通過控制變數法得以論證其優先順序由高到底,高優先順序的配置會覆蓋低優先順序的配置
3.自定義配置屬性
SpringBoot提供了許多的配置,但通常情況我們需要自定義自己的配置應用自己的系統中,如你需要配置一個預設的使用者名稱密碼做為系統的登入用。
首先建立一個實體類,作為配置注入用,並使用**@ConfigurationProperties註解進行批量注入, 也可以使用Spring底層註解@Value("${user.username}")**的方式一個一個注入達到同意的效果
@Component
@ConfigurationProperties(prefix = "user")
public class Login{
private String username;
private String password;
...
}
或者@Value寫法
@Component
public class Login{
private String username;
private String password;
...
}
配置yaml檔案
user:
username: admin
password: 123
或者properties檔案
login.username=admin
login.password=123
編寫一個junit測試用例,看看配置的值是否正常注入:
@RunWith(SpringRunner.class)
@SpringBootTest
public class DeployApplicationTests {
@Autowired
private Login login;
@Test
public void contextLoads() {
System.out.println(login);
}
}
從輸出結果上看,值已正常注入
Login{username=‘admin’, password=‘123’}
@ConfigurationProperties與@Value兩種註解對比
比較項 | @ConfigurationProperties | @Value |
---|---|---|
全量注入 | 支援 | 否 |
鬆散繫結(Relaxed binding) | 支援 | 否 |
SpEL | 否 | 支援 |
JSR303 | 支援 | 不支援 |
**鬆散繫結:**駝峰命名(userName)、橫幹拼接(user-name)、下劃線(user_name)之間可以互相識別繫結稱為做鬆散繫結
**JSR303:**通過@Email,@Nullable,@Digits 等等註解進行郵箱、判空、數字格式等等資料的校驗,更多相關內容請參考IBM的中文文件:https://www.ibm.com/developerworks/cn/java/j-lo-jsr303/index.html
@ConfigurationProperties通常用於將配置全量注入某個類中;
@Value通常用於注入某一些特定配置值中;
自定義配置提示
在編寫配置時,你會發現自定義配置沒有提示,讓你在使用自定義配置時變的很麻煩,其實SpringBoot早已為我們準備好了提示的需要,只需要用引入相關依賴即可有提示。
在沒有加入依賴時idea會有如下提示:
新增依賴,該idea提示便消失,編寫自定義配置時也有相應提示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
需要執行一下
4.指定配置檔案
通常情況下我們將配置配置在application開頭的主配置檔案中,這樣隨著專案的增大配置項的增多會使檔案變得非常臃腫,其實SpringBoot早已考慮到了該問題,SpringBoot提供了**@PropertySource和@ImportResource**兩個註解用於載入外部配置檔案使用。
- @PropertySource通常用於屬性載入配置檔案,注意@PropertySource註解不支援載入yaml檔案,支援properties檔案。
- @ImportResource通常用於載入Spring的xml配置檔案
@PropertySource使用
裝配properties配置檔案
在sources/config下建立一個yaml檔案命名為user.properties內容與上方user的配置一樣
Login類可如下寫法
@PropertySource(value = {"classpath:config/user.properties"})
@Component
@ConfigurationProperties(prefix = "user")
public class Login{
private String username;
private String password;
...
}
執行一下,同樣能達到載入配置效果
同時載入多個配置問題
細心的你,會發現@PropertySource註解中屬性value為一個數組,如果同時載入多個配置檔案,並且不同配置檔案中對同一個屬性設定了不同的值,那麼Spring會識別哪一個呢?
帶著疑問,我們可以通過控制變數法進行測試,具體過程再在贅述。
@PropertySource(value = {"classpath:config/user1.properties","classpath:config/user2.properties"})
結論:Spring載入順序為從左到右順序載入,後加載的會覆蓋先載入的屬性值。
裝配yaml配置檔案
如果你有強迫症,一定想載入yaml配置檔案,那麼可以通過PropertySourcesPlaceholderConfigurer類來載入yaml檔案,將原來的user.properties改成user.yaml,Bean配置類中加入如下程式碼,Login配置類和一開始的方式一致。
@Bean
public static PropertySourcesPlaceholderConfigurer loadProperties() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
//yaml.setResources(new FileSystemResource("classpath:config/user.yml"));//File路徑引入
yaml.setResources(new ClassPathResource("config/user.yml"));//class路徑引入
configurer.setProperties(yaml.getObject());
return configurer;
}
執行一下,仍然可以能達到載入配置效果的
@ImportResource使用
SpringBoot提出零xml的配置,因此SpringBoot預設情況下時不會識別專案中Spring的xml配置檔案。為了能夠載入xml的配置檔案,SpringBoot提供了@ImportResource註解該註解可以載入Spring的xml配置檔案,通常加於啟動類上。
@ImportResource(value = {"classpath:/beans.xml"})
@SpringBootApplication(scanBasePackages = {"team.seagull.client"})
public class DeployApplication {
public static void main(String[] args) {
SpringApplication.run(DeployApplication.class, args);
}
}
其他問題
idea使用*.properties檔案出現中文亂碼問題?
idea對*.properties預設編碼為GBK,通常我們專案為UTF-8編碼,這樣程式在讀取時就會出現亂碼問題;
解決方法:idea 中 開啟如下選項File->Sttings->Editor->FileEncodings
將GBK修改為UTF-8並勾選
Transparent native-to ascill conversion(在執行的時候轉換成ascii碼)