关于SpringBoot配置文件 加载多个外部自定义配置文件
Spring Boot项目最终我们会发布为一个jar或war文件部署到生产环境,这十分方便,但在生产环境中我们会遇到一个问题:
Spring Boot在打包时,将项目下所有文件全部压缩到了jar文件内,这使得我们在生产环境下每需要修改某个配置文件属性都需要将项目重新发布,相当反人类。
那么要解决这个问题,我们就需要让项目引用外部配置文件,那么在实际开发环境下,可能我们会存在多个配置文件(我很排斥使用Spring Boot的 Application.Properties作为我项目的配置文件,可能是某种精神洁癖。)比如在我的项目中我目前使用了两个配置文件:
redis.Properties //redis的配置信息
sysconf.Properties //系统配置信息
那么,如何在Spring Boot 中引用外部配置文件?
在开始之前,我们先来了解以下Spring Boot的默认配置文件加载流程,Spring Boot中规定默认配置文件名称为:Application.Properties,如果使用默认配置文件,则系统会自动处理文件内外部关系,我们可以看到SpringBoot源码中的加载顺序,优先级从高到低为:
#ConfigFileApplicationListener.java
private void load(Profile profile, DocumentFilterFactory filterFactory,
DocumentConsumer consumer) {
//getSearchLocations()默认返回:
//[./config/, file:./, classpath:/config/, classpath:/]
//即搜索这些路径下的文件
getSearchLocations().forEach((location) -> {
boolean isFolder = location.endsWith("/");
//getSearchNames()返回:application
Set<String> names = (isFolder ? getSearchNames() : NO_SEARCH_NAMES);
//跟入load(.....)
names.forEach(
(name) -> load(location, name, profile, filterFactory, consumer));
});
}
./config/(系统运行根目录config文件夹下)
file:./ (系统运行根目录下)
classpath:/config/ (jar包内resources文件夹config文件夹下)
classpath:/ (jar包内resources文件夹下)
也就是说,如果我们使用application作为配置文件,我们只需要把配置文件放在jar包根目录下,根据优先级,boot会优先选择根目录下的配置文件。
但是,我们上面说过,我不想使用默认文件命名,而且我会有多个配置文件,这样我们如何来做呢?
如何在Spring Boot 中引用多个自定义外部配置文件呢?
这里我们需要用到boot的注解方式导入配置文件,@PropertySource()注释可以让我们自定义导入配置文件,使用方法如下:
@PropertySource(value= {"$配置文件路径"},ignoreResourceNotFound = true)
ignoreResourceNotFound 表示如果配置文件找不到是否报错 true:不报错 false:报错
在项目中应用代码如下:
@RestController
@CrossOrigin
@PropertySource(value= {"classpath:config/sysconf.Properties","file:config/sysconf.Properties"},ignoreResourceNotFound = true)
public class spartacus_nodeinteractive
{
@Value("${syslog_ip}")
String syslog_ip;
@RequestMapping(value="/test",method = RequestMethod.GET)
private String test(HttpServletRequest request,HttpServletResponse response)
{
return syslog_ip;
}
}
@PropertySource中我添加了两个配置文件路径,外部文件路径和内部文件路径,这样可以让我的系统在没有外部配置文件时也可以正常运行,注意加载顺序,经过测试排在后面的路径优先级高于前面的路径,也就是说这个项目里会以外部配置文件为*别。
classpath:表示在包内寻找
file:表示在指定路径下寻找
应用后通过@Value注释获取对应值,多个配置文件就添加多个文件路径,注意优先级顺序就可以了。
然后我们又遇到一个新的问题,每个控制器我都需要加一边配置文件注释,然后都需要使用@value获取一边,这不是代码冗余了吗?解决这个问题,我们可以将配置封装成一个对象
@Component
@ConfigurationProperties(prefix="")
@PropertySource(value= {"classpath:config/sysconf.Properties","file:config/sysconf.Properties"},ignoreResourceNotFound = true)
/**
* @author Song
* @category syconf配置文件
* @serial 【2020年9月18日】 建立函数
*/
public class sysconf
{
private String syslog_ip;
private String syslog_port;
private String debug_log;
public String getSyslog_ip() {
return syslog_ip;
}
public void setSyslog_ip(String syslog_ip) {
this.syslog_ip = syslog_ip;
}
public String getSyslog_port() {
return syslog_port;
}
public void setSyslog_port(String syslog_port) {
this.syslog_port = syslog_port;
}
public String getDebug_log() {
return debug_log;
}
public void setDebug_log(String debug_log) {
this.debug_log = debug_log;
}
}
封装注意类中变量名与配置文件中的配置属性名相同。
使用方法如下:
@EnableConfigurationProperties(sysconf.class) //启用系统配置文件 可以直接放在application下
@Autowired
sysconf sysconf;//加载配置文件
sysconf.getSyslog_ip();
@RestController
@CrossOrigin
@EnableConfigurationProperties(sysconf.class)//加载系统配置文件 可以放到app启动类里这里为了方便演示
public class spartacus_nodeinteractive
{
@Autowired
sysconf sysconf;//加载配置文件
@RequestMapping(value="/test",method = RequestMethod.GET)
private String test(HttpServletRequest request,HttpServletResponse response)
{
return sysconf.getSyslog_ip();
}
}
这样就方便很多了吧。到此就结束了.....................................不!没有。
———————————————华丽的分割线——————————————
使用上面这种写法时,调用配置文件的所在类必须是被Spring管理的Bean类,也就是使用了@Service、@Controller、@Component、@Configuration等注解的类。那么非管理的类中如何使用配置文件呢?我们需要通过SpringBoot的上下文信息来获取配置文件信息。
config.content = SpringApplication.run(App.class, args);//启动时获取spring上下文
public class config
{
public static ApplicationContext content;//静态对象用来储存上下文信息
}
String bind_ip = config.content.getEnvironment().getProperty("syslog_ip");//从上下文中获取需要的配置信息
这样总算结束了....写了2个小时....总之技术还要活学活用,实在不行查源码,告辞!
上一篇: 解决ASP.NET中"/"应用程序中的服务器错误的方法
下一篇: javaEE Filter