基于springboot实现自定义配置文件外部挂载
背景
spring支持载入jar包外的配置,但是仅仅只对application.properties主配置文件支持。这问题就大了,正式开发肯定不会把所有配置都写在主配置文件中。
理论
@PropertySource
注解有一个factory
参数,默认值是PropertySourceFactory.class
,默认实现是DefaultPropertySourceFactory.class
,这个参数就是用来指定配置文件加载工厂类的。
默认的实现是从jar包内查找配置文件,同时spring还有自带的外部文件资源类FileSystemResource
,那要做的事情就很明显了。
spring默认的不是从jar包内查找吗,那我不变spring的原逻辑,我在它的基础上再加一层。不仅从jar内查找,额外从jar包外查找。规则如下:
jar包内有,jar包外没有,那自然是用jar包内的配置。
jar包内没有,jar包外有,自然是用jar包外的配置。
jar包内有,jar包外也有,使用jar包外的配置。
注意:这里是替换关系,不是补充关系。
编码
TomPropertySourceFactory 自定义配置文件载入工厂类
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
/**
* @author TomShiDi
* @description
* @date 2022/3/14 21:30
**/
public class TomPropertySourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
Resource fileSystemResource = null;
// 判断jar包类有没有找到配置
if (encodedResource.getResource() instanceof ClassPathResource) {
String path = ((ClassPathResource) encodedResource.getResource()).getPath();
fileSystemResource = new FileSystemResource(path);
}
// 如果外部配置也存在,则替换掉jar包内的配置
if (fileSystemResource != null && fileSystemResource.exists()) {
encodedResource = new EncodedResource(fileSystemResource, encodedResource.getEncoding());
}
// 调用原spring逻辑
return super.createPropertySource(name, encodedResource);
}
}
extra-config.properties 配置文件
extra.name=tomshidi
extra.properties.age=1000
extra.properties.sex='M'
ExtraConfig 配置类
import com.example.demo.factory.TomPropertySourceFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author TomShiDi
* @description
* @date 2022/3/14 21:32
**/
@Component
@PropertySource(value = "classpath:config/extra-config.properties",
encoding = "UTF-8",
factory = TomPropertySourceFactory.class)
@ConfigurationProperties(prefix = "extra")
public class ExtraConfig {
private String name;
private Map<String, Object> properties;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, Object> getProperties() {
return properties;
}
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}
@Override
public String toString() {
return "ExtraConfig{" +
"name='" + name + '\'' +
", properties=" + properties +
'}';
}
}
运行效果
载入外部文件
目录结构如下
配置文件内容
extra.name='This is an extra properties'
extra.properties.age=1000
extra.properties.sex='M'