Spring Boot讀取自定義配置文件
@Value
首先,會(huì)想到使用@Value注解,該注解只能去解析yaml文件中的簡(jiǎn)單類(lèi)型,并綁定到對(duì)象屬性中去。
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
對(duì)于上面的yaml配置,如果我們使用@Value注解的話,冒號(hào)后面直接有值的key才能正確注入對(duì)應(yīng)的值。例如felord.phone我們可以通過(guò)@Value獲取,但是felord.def不行,因?yàn)閒elord.def后面沒(méi)有直接的值,它還有下一級(jí)選項(xiàng)。另外@Value不支持yaml松散綁定語(yǔ)法,也就是說(shuō)felord.def.weChat獲取不到felord.def.we-chat的值。
@Value是通過(guò)使用Spring的SpEL表達(dá)式來(lái)獲取對(duì)應(yīng)的值的:
// 獲取 yaml 中 felord.phone的值 并提供默認(rèn)值 UNKNOWN @Value("${felord.phone:UNKNOWN}") private String phone;
@Value的使用場(chǎng)景是只需要獲取配置文件中的某項(xiàng)值的情況下,如果我們需要將一個(gè)系列的值進(jìn)行綁定注入就建議使用復(fù)雜對(duì)象的形式進(jìn)行注入了。
@ConfigurationProperties
@ConfigurationProperties注解提供了我們將多個(gè)配置選項(xiàng)注入復(fù)雜對(duì)象的能力。它要求我們指定配置的共同前綴。比如我們要綁定felord.def下的所有配置項(xiàng):
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的值,因?yàn)檫@種形式支持從駝峰camel-case到短橫分隔命名kebab-case的自動(dòng)轉(zhuǎn)換。
如果我們使用@ConfigurationProperties的話建議配置類(lèi)命名后綴為Properties,比如Redis的后綴就是RedisProperties,RabbitMQ的為RabbitProperties。
另外我們?nèi)绻脒M(jìn)行嵌套的話可以借助于@NestedConfigurationProperty注解實(shí)現(xiàn)。也可以借助于內(nèi)部類(lèi)。這里用內(nèi)部類(lèi)實(shí)現(xiàn)將開(kāi)頭yaml中所有的屬性進(jìn)行注入:
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)部類(lè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 } }
單獨(dú)使用@ConfigurationProperties的話依然無(wú)法直接使用配置對(duì)象FelordDefProperties,因?yàn)樗](méi)有被注冊(cè)為Spring Bean。我們可以通過(guò)兩種方式來(lái)使得它生效。
顯式注入 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進(jìn)行注冊(cè),這樣就不需要顯式聲明配置類(lèi)為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} 注冊(cè) {@link FelordDevProperties}使之生效 * @author felord.cn */ @EnableConfigurationProperties({FelordDevProperties.class}) @Configuration public class FelordConfiguration { }
該注解需要顯式的注冊(cè)對(duì)應(yīng)的配置類(lèi)。
@ConfigurationPropertiesScan
在Spring Boot 2.2.0.RELEASE中提供了一個(gè)掃描注解@ConfigurationPropertiesScan。它可以掃描特定包下所有的被@ConfigurationProperties標(biāo)記的配置類(lèi),并將它們進(jìn)行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); } }
這非常適合自動(dòng)注入和批量注入配置類(lèi)的場(chǎng)景,但是有版本限制,必須在2.2.0及以上。
@PropertySource注解
@PropertySource可以用來(lái)加載指定的配置文件,默認(rèn)它只能加載*.properties文件,不能加載諸如yaml等文件。
@PropertySource相關(guān)屬性介紹
- value:指明加載配置文件的路徑。
- ignoreResourceNotFound:指定的配置文件不存在是否報(bào)錯(cuò),默認(rèn)是false。當(dāng)設(shè)置為 true 時(shí),若該文件不存在,程序不會(huì)報(bào)錯(cuò)。實(shí)際項(xiàng)目開(kāi)發(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注解了。當(dāng)我們使用@Value需要注入的值較多時(shí),代碼就會(huì)顯得冗余。我們可以使用@ConfigurationProperties 中的 prefix 用來(lái)指明我們配置文件中需要注入信息的前綴
前邊提到了用@PropertySource只能加載*.properties文件,但如果我們項(xiàng)目的配置文件不是*.properties這種類(lèi)型,而是其他類(lèi)型,諸如yaml,此時(shí)我們可以通過(guò)實(shí)現(xiàn)PropertySourceFactory接口,重寫(xiě)createPropertySource方法,就能實(shí)現(xiàn)用@PropertySource也能加載yaml等類(lèi)型文件。
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、實(shí)現(xiàn)EnvironmentPostProcessor接口,重寫(xiě)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步驟實(shí)現(xiàn)完后,就可以在代碼中直接用@Value的方式獲取自定義配置文件內(nèi)容了
讀取的自定義配置文件內(nèi)容的實(shí)現(xiàn)方法有多種多樣,除了上面的方法,還可以在以-jar方式啟動(dòng)時(shí),執(zhí)行形如下命令
java -jar project.jar --spring.config.location=classpath:/config/custom.yml
也能實(shí)現(xiàn)。還可以干脆自定義配置文件都以application-*為前綴,比如application-custom,然后在application.properties,使用spring.profiles.include=custom或者spring.profiles.active=custom也可以實(shí)現(xiàn)
總結(jié)
日常開(kāi)發(fā)中單個(gè)屬性推薦使用@Value,如果同一組屬性為多個(gè)則推薦@ConfigurationProperties。需要補(bǔ)充一點(diǎn)的是@ConfigurationProperties還支持使用 JSR303 進(jìn)行屬性校驗(yàn)。好了今天的教程就到這里
相關(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讀取自定義配置文件的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot讀取自定義配置文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot整合Netty+Websocket實(shí)現(xiàn)消息推送的示例代碼
WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù),本文主要介紹了SpringBoot整合Netty+Websocket實(shí)現(xiàn)消息推送的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01Java實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲
這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07Java實(shí)現(xiàn)自動(dòng)壓縮文件并加密的方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)自動(dòng)壓縮文件并加密的方法,涉及java針對(duì)文件進(jìn)行zip壓縮并加密的相關(guān)操作技巧,需要的朋友可以參考下2018-01-01JAVA使用前綴樹(shù)(Tire樹(shù))實(shí)現(xiàn)敏感詞過(guò)濾、詞典搜索
本文主要介紹了JAVA使用前綴樹(shù)(Tire樹(shù))實(shí)現(xiàn)敏感詞過(guò)濾、詞典搜索,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01淺析Java.IO輸入輸出流 過(guò)濾流 buffer流和data流
這篇文章主要介紹了Java.IO輸入輸出流 過(guò)濾流 buffer流和data流的相關(guān)資料,本文給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10Java局部?jī)?nèi)部類(lèi)和匿名內(nèi)部類(lèi)定義與用法實(shí)例分析
這篇文章主要介紹了Java局部?jī)?nèi)部類(lèi)和匿名內(nèi)部類(lèi),結(jié)合實(shí)例形式分析了java局部?jī)?nèi)部類(lèi)和匿名內(nèi)部類(lèi)相關(guān)定義、原理與用法,需要的朋友可以參考下2019-08-08IntelliJ?IDEA?2022安裝注冊(cè)永久激活
java開(kāi)發(fā)工具IntelliJ?IDEA深受用戶喜愛(ài),很多朋友對(duì)這個(gè)idea開(kāi)發(fā)工具比較忠心,一旦有新版本發(fā)出,很多小伙伴就迫不及待的想更新,今天小編給大家?guī)?lái)了idea2022.1最新永久激活碼,親測(cè)有效,喜歡的朋友快來(lái)下載體驗(yàn)吧2022-08-08