SpringBoot加载自定义配置文件
前言
SpringBoot的配置文件是application.properties或者application.yml。我们还可以根据spring.profiles.active配置项添加application-dev.properties或者application-prod.properties。这样,SpringBoot启动的时候就会自动添加对应环境的配置文件。但是,我们还想自定义一些配置文件。比如ES相关的配置文,我们想放在es.properties配置文件里,这样就不会导致application.properties配置文件的配置项过多,而且也方便查找,尤其是项目配置项特别多的时候。
网上的一般做法是使用@PropertySource注解来加载自定义配置文件。@PropertySource可以放在启动类上,加载所有自己想加载的配置文件,也可以放在任意配置类上,结合@ConfigurationProperties注解使用。但是spring的官方文档并不推荐这么使用,所以,我们根据官方文档的方法来尝试一下。
一、配置文件
我们先把不同环境的配置文件放在不同的文件夹里。如下图所示,dev开发环境的配置文件全部在dev文件夹下,prod生产环境的配置文件全部放在prod文件夹下。
此时,自定义的wayne-es.properties配置文件并未被idea识别为SpringBoot的配置文件,添加配置的时候并没有任何提示。所以要把wayne-es.properties添加到配置文件中。根据下图一步一步操作,就可以把自定义的配置文件添加到SpringBoot配置文件中。
二、配置pom文件
经过上面的一些配置之后,不同环境的配置文件就会有很多,但是项目运行的时候只需要一种环境的配置文件。所以,就需要在编译的时候做一些操作,只保留想要的某个环境下的配置文件。这个时候就需要配置一下pom文件,添加一些配置或者插件来实现相关操作。
2.1 配置 profiles
首先要先定义一下有哪些运行环境,一般有dev,test,prod。这些名字啥的都可以自己随便定义。具体配置如下:
<profiles>
<profile>
<!-- 生产环境 -->
<id>prod</id>
<properties>
<profileActive>prod</profileActive>
</properties>
</profile>
<profile>
<!-- 本地开发环境 -->
<id>dev</id>
<properties>
<profileActive>dev</profileActive>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 测试环境 -->
<id>test</id>
<properties>
<profileActive>test</profileActive>
</properties>
</profile>
</profiles>
注意properties下的profileActive是自定义的一个变量,随便什么名字都可以。activeByDefault的意思是spring.profiles.active = dev。这样一来,在application.properties配置文件里就可以直接引用profileActive来进行运行环境的配置了。
spring.profiles.active=@profileActive@
两个@的意思是引用pom文件下profileActive变量的意思。可以在启动的时候查看一下日志,就知道profileActive值是什么了。
另外idea自带的maven插件也可以设置profileActive的值。这个插件在idea的右侧菜单栏里。
Profiles下默认只有dev,其下面的值是根据你配置的profiles下的profile的id自动生成的。
2.2 配置resources
接下来配置编译时的逻辑,排除不需要的配置文件,把需要的配置文件放到resources根目录下。profileActive是引用的上一步配置的变量,project.build.directory是项目编译后的根目录,即target目录。
<build>
<resources>
<resource>
<!--配置文件路径-->
<directory>src/main/resources</directory>
<!--开启filtering功能 -->
<filtering>true</filtering>
<!-- 排除文件 -->
<excludes>
<exclude>dev</exclude>
<exclude>dev/*</exclude>
<exclude>test</exclude>
<exclude>test/*</exclude>
<exclude>prod</exclude>
<exclude>prod/*</exclude>
</excludes>
</resource>
<!--将对应环境的资源配置,构建到最顶层-->
<resource>
<directory>src/main/resources/${profileActive}</directory>
<filtering>false</filtering>
<targetPath>${project.build.directory}/classes</targetPath>
</resource>
</resources>
</build>
三、加载自定义配置文件
根据spring官方文档,需要实现EnvironmentPostProcessor来加载自定义配置文件。注意,该实现类不需要添加任何注解!!
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {
//配置文件名称匹配
private ResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver();
//配置文件加载处理器
private List<PropertySourceLoader> propertySourceLoaders;
public CustomEnvironmentPostProcessor() {
super();
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
for (PropertySourceLoader loader : this.propertySourceLoaders) {
for (String fileExtension : loader.getFileExtensions()) {
//这里定义了一下配置文件的前缀【wayne-】,加载所有前缀为wayne-的配置文件。前缀可以自定义
String location = ResourceUtils.CLASSPATH_URL_PREFIX + "wayne-*." + fileExtension;
try {
Resource[] resources = this.resourceLoader.getResources(location);
for (Resource resource : resources) {
List<PropertySource<?>> propertySources = loader.load(resource.getFilename(), resource);
if (!CollectionUtils.isEmpty(propertySources)){
System.out.println("加载配置文件:" + propertySources);
propertySources.forEach(environment.getPropertySources()::addLast);
}
}
} catch (IOException e) {
System.out.println("配置文件加载失败:" + e.getMessage());
}
}
}
}
}
然后在resources下新建META-INF文件夹,文件夹里新建spring.factories文件。在spring.factories里添加配置即可,前面是固定的,后面是你的实现类的全类名。
org.springframework.boot.env.EnvironmentPostProcessor=com.wayne.config.CustomEnvironmentPostProcessor
这样,就会在启动类运行之前,把自定义的配置文件加载进去了。
我们可以实验一下,在启动类中读取一下自定义配置文件的内容,wayne-es.properties添加spring.elasticsearch=master配置,然后在启动类中添加如下代码。
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(EsSyncToolApplication.class, args);
String property = context.getEnvironment().getProperty("spring.elasticsearch");
System.out.println(property);
}
如图所示,自定义配置文件加载成功,配置文件里的配置内容也读取成功。
写在最后的话
如果配置项不是很多的话,就不需要加载自定义配置文件了,卸载一个文件里就解决了,没必要搞这么麻烦。