自定义的配置文件,如何注入到SpringBoot?
suiw9 2025-03-14 20:30 8 浏览 0 评论
一、简介
在实际的项目开发过程中,我们经常需要将某些变量从代码里面抽离出来,放在配置文件里面,以便更加统一、灵活的管理服务配置信息。比如,数据库、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 map1 = new HashMap<>();
private Map 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 userList;
public List getUserList() {
return userList;
}
public void setUserList(List 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);
}
}
相关推荐
- 俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)
-
发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...
- 如何强制所有流量使用 HTTPS一网上用户
-
如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...
- https和http的区别(https和http有何区别)
-
“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...
- 快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别
-
什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...
- 简述HTTPS工作原理(简述https原理,以及与http的区别)
-
https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...
- 21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)
-
HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...
- 一次安全可靠的通信——HTTPS原理
-
为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...
- 为什么有的网站没有使用https(为什么有的网站点不开)
-
有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...
- HTTPS是什么?加密原理和证书。SSL/TLS握手过程
-
秘钥的产生过程非对称加密...
- 图解HTTPS「转」(图解http 完整版 彩色版 pdf)
-
我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...
- HTTP 和 HTTPS 有何不同?一文带你全面了解
-
随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...
- HTTP与HTTPS的区别,详细介绍(http与https有什么区别)
-
HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...
- 一文让你轻松掌握 HTTPS(https详解)
-
一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...
- 如何在Spring Boot应用程序上启用HTTPS?
-
HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...
- 一文彻底搞明白Http以及Https(http0)
-
早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
tinymce 号称富文本编辑器世界第一,大家同意么?
-
- 最近发表
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)