Spring Boot讀取自定義配置文件
@Value
首先,會想到使用@Value注解,該注解只能去解析yaml文件中的簡單類型,并綁定到對象屬性中去。
felord: phone: 182******32 def: name: 碼農(nóng)小胖哥 blog: felord.cn we-chat: MSW_623 dev: name: 碼農(nóng)小胖哥 blog: felord.cn we-chat: MSW_623 type: JUEJIN
對于上面的yaml配置,如果我們使用@Value注解的話,冒號后面直接有值的key才能正確注入對應(yīng)的值。例如felord.phone我們可以通過@Value獲取,但是felord.def不行,因為felord.def后面沒有直接的值,它還有下一級選項。另外@Value不支持yaml松散綁定語法,也就是說felord.def.weChat獲取不到felord.def.we-chat的值。
@Value是通過使用Spring的SpEL表達式來獲取對應(yīng)的值的:
// 獲取 yaml 中 felord.phone的值 并提供默認值 UNKNOWN
@Value("${felord.phone:UNKNOWN}")
private String phone;
@Value的使用場景是只需要獲取配置文件中的某項值的情況下,如果我們需要將一個系列的值進行綁定注入就建議使用復(fù)雜對象的形式進行注入了。
@ConfigurationProperties
@ConfigurationProperties注解提供了我們將多個配置選項注入復(fù)雜對象的能力。它要求我們指定配置的共同前綴。比如我們要綁定felord.def下的所有配置項:
package cn.felord.yaml.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static cn.felord.yaml.properties.FelordDefProperties.PREFIX;
/**
* @author felord.cn
*/
@Data
@ConfigurationProperties(PREFIX)
public class FelordDefProperties {
static final String PREFIX = "felord.def";
private String name;
private String blog;
private String weChat;
}
我們注意到我們可以使用weChat接收we-chat的值,因為這種形式支持從駝峰camel-case到短橫分隔命名kebab-case的自動轉(zhuǎn)換。
如果我們使用@ConfigurationProperties的話建議配置類命名后綴為Properties,比如Redis的后綴就是RedisProperties,RabbitMQ的為RabbitProperties。
另外我們?nèi)绻脒M行嵌套的話可以借助于@NestedConfigurationProperty注解實現(xiàn)。也可以借助于內(nèi)部類。這里用內(nèi)部類實現(xiàn)將開頭yaml中所有的屬性進行注入:
package cn.felord.yaml.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static cn.felord.yaml.properties.FelordProperties.PREFIX;
/**
* 內(nèi)部類和枚舉配置.
*
* @author felord.cn
*/
@Data
@ConfigurationProperties(PREFIX)
public class FelordProperties {
static final String PREFIX = "felord";
private Def def;
private Dev dev;
private Type type;
@Data
public static class Def {
private String name;
private String blog;
private String weChat;
}
@Data
public static class Dev {
private String name;
private String blog;
private String weChat;
}
public enum Type {
JUEJIN,
SF,
OSC,
CSDN
}
}
單獨使用@ConfigurationProperties的話依然無法直接使用配置對象FelordDefProperties,因為它并沒有被注冊為Spring Bean。我們可以通過兩種方式來使得它生效。
顯式注入 Spring IoC
你可以使用@Component、@Configuration等注解將FelordDefProperties注入Spring IoC使之生效。
package cn.felord.yaml.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import static cn.felord.yaml.properties.FelordDefProperties.PREFIX;
/**
* 顯式注入Spring IoC
* @author felord.cn
*/
@Data
@Component
@ConfigurationProperties(PREFIX)
public class FelordDefProperties {
static final String PREFIX = "felord.def";
private String name;
private String blog;
private String weChat;
}
@EnableConfigurationProperties
我們還可以使用注解@EnableConfigurationProperties進行注冊,這樣就不需要顯式聲明配置類為Spring Bean了。
package cn.felord.yaml.configuration;
import cn.felord.yaml.properties.FelordDevProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 使用 {@link EnableConfigurationProperties} 注冊 {@link FelordDevProperties}使之生效
* @author felord.cn
*/
@EnableConfigurationProperties({FelordDevProperties.class})
@Configuration
public class FelordConfiguration {
}
該注解需要顯式的注冊對應(yīng)的配置類。
@ConfigurationPropertiesScan
在Spring Boot 2.2.0.RELEASE中提供了一個掃描注解@ConfigurationPropertiesScan。它可以掃描特定包下所有的被@ConfigurationProperties標記的配置類,并將它們進行IoC注入。
package cn.felord.yaml;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* {@link ConfigurationPropertiesScan} 同 {@link EnableConfigurationProperties} 二選一
*
* @see cn.felord.yaml.configuration.FelordConfiguration
* @author felord.cn
*/
@ConfigurationPropertiesScan
@SpringBootApplication
public class SpringBootYamlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootYamlApplication.class, args);
}
}
這非常適合自動注入和批量注入配置類的場景,但是有版本限制,必須在2.2.0及以上。
@PropertySource注解
@PropertySource可以用來加載指定的配置文件,默認它只能加載*.properties文件,不能加載諸如yaml等文件。
@PropertySource相關(guān)屬性介紹
- value:指明加載配置文件的路徑。
- ignoreResourceNotFound:指定的配置文件不存在是否報錯,默認是false。當設(shè)置為 true 時,若該文件不存在,程序不會報錯。實際項目開發(fā)中,最好設(shè)置 ignoreResourceNotFound 為 false。
- encoding:指定讀取屬性文件所使用的編碼,我們通常使用的是UTF-8。
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Configuration
@PropertySource(value = {"classpath:common.properties"},ignoreResourceNotFound=false,encoding="UTF-8")
@ConfigurationProperties(prefix = "author")
public class Author {
private String name;
private String job;
private String sex;
}
有小伙伴也許發(fā)現(xiàn)示例上的@ConfigurationProperties注解了。當我們使用@Value需要注入的值較多時,代碼就會顯得冗余。我們可以使用@ConfigurationProperties 中的 prefix 用來指明我們配置文件中需要注入信息的前綴
前邊提到了用@PropertySource只能加載*.properties文件,但如果我們項目的配置文件不是*.properties這種類型,而是其他類型,諸如yaml,此時我們可以通過實現(xiàn)PropertySourceFactory接口,重寫createPropertySource方法,就能實現(xiàn)用@PropertySource也能加載yaml等類型文件。
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String sourceName, EncodedResource resource) throws IOException {
Properties propertiesFromYaml = loadYaml(resource);
if(StringUtils.isBlank(sourceName)){
sourceName = resource.getResource().getFilename();;
}
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
}
private Properties loadYaml(EncodedResource resource) throws FileNotFoundException {
try {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
} catch (IllegalStateException e) {
// for ignoreResourceNotFound
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException)
throw (FileNotFoundException) e.getCause();
throw e;
}
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Configuration
@PropertySource(factory = YamlPropertySourceFactory.class,value = {"classpath:user.yml"},ignoreResourceNotFound=false,encoding="UTF-8")
@ConfigurationProperties(prefix = "user")
public class User {
private String username;
private String password;
}
使用EnvironmentPostProcessor加載自定義配置文件
1、實現(xiàn)EnvironmentPostProcessor接口,重寫postProcessEnvironment方法
@Slf4j
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Properties properties = new Properties();
try {
properties.load(new InputStreamReader(CustomEnvironmentPostProcessor.class.getClassLoader().getResourceAsStream("custom.properties"),"UTF-8"));
PropertiesPropertySource propertiesPropertySource = new PropertiesPropertySource("custom",properties);
environment.getPropertySources().addLast(propertiesPropertySource);
} catch (IOException e) {
log.error(e.getMessage(),e);
}
}
}
2、在META-INF下創(chuàng)建spring.factories
spring.factories文件內(nèi)容如下: org.springframework.boot.env.EnvironmentPostProcessor=com.github.lybgeek.env.CustomEnvironmentPostProcessor
1、2步驟實現(xiàn)完后,就可以在代碼中直接用@Value的方式獲取自定義配置文件內(nèi)容了
讀取的自定義配置文件內(nèi)容的實現(xiàn)方法有多種多樣,除了上面的方法,還可以在以-jar方式啟動時,執(zhí)行形如下命令
java -jar project.jar --spring.config.location=classpath:/config/custom.yml
也能實現(xiàn)。還可以干脆自定義配置文件都以application-*為前綴,比如application-custom,然后在application.properties,使用spring.profiles.include=custom或者spring.profiles.active=custom也可以實現(xiàn)
總結(jié)
日常開發(fā)中單個屬性推薦使用@Value,如果同一組屬性為多個則推薦@ConfigurationProperties。需要補充一點的是@ConfigurationProperties還支持使用 JSR303 進行屬性校驗。好了今天的教程就到這里
相關(guān)的demo地址
https://gitee.com/felord/spring-boot-yml.git
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-outside-config
以上就是Spring Boot讀取自定義配置文件的詳細內(nèi)容,更多關(guān)于Spring Boot讀取自定義配置文件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot整合Netty+Websocket實現(xiàn)消息推送的示例代碼
WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù),本文主要介紹了SpringBoot整合Netty+Websocket實現(xiàn)消息推送的示例代碼,具有一定的參考價值,感興趣的可以了解一下2024-01-01
JAVA使用前綴樹(Tire樹)實現(xiàn)敏感詞過濾、詞典搜索
本文主要介紹了JAVA使用前綴樹(Tire樹)實現(xiàn)敏感詞過濾、詞典搜索,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-01-01
淺析Java.IO輸入輸出流 過濾流 buffer流和data流
這篇文章主要介紹了Java.IO輸入輸出流 過濾流 buffer流和data流的相關(guān)資料,本文給大家介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下2016-10-10
Java局部內(nèi)部類和匿名內(nèi)部類定義與用法實例分析
這篇文章主要介紹了Java局部內(nèi)部類和匿名內(nèi)部類,結(jié)合實例形式分析了java局部內(nèi)部類和匿名內(nèi)部類相關(guān)定義、原理與用法,需要的朋友可以參考下2019-08-08

