前言
springcloud提供了PropertySourceLocator接口支持扩展自定义配置加载到spring Environment中。
即我们可以扩展PropertySourceLocator让spring读取我们自定义的配置文件,然后使用@Value注解即可读取到配置文件中的属性了
代码实现
首先我们在resources下面创建我们自己的配置文件my.json,文件内容为
{
"my":{
"json":{
"property": "my json properties"
}
}
}
我们希望加载my.json.property到spring的Environment中
扩展PropertySourceLocator
/**
* @description
* 基于springcloud提供的PropertySourceLocator扩展配置文件,读取classpath下的my.json文件配置加载到spring环境变量中
* 1、pom.xml依赖spring-cloud-starter包
* 2、编写JsonPropertySourceLocator文件
* 3、编写locate方法
* 4、基于SPI方式在classpath下META-INF/spring.factories文件定义
* org.springframework.cloud.bootstrap.BootstrapConfiguration=自定义JsonPropertySourceLocator
*
*/
public class JsonPropertySourceLocator implements PropertySourceLocator {
private final static String DEFAULT_LOCATION = "classpath:my.json";
@Override
public PropertySource<?> locate(Environment environment) {
// TODO 微服务配置中心实现形式即可在这里远程RPC加载配置到spring环境变量中
// 读取classpath下的my.json解析
ResourceLoader resourceLoader = new DefaultResourceLoader(getClass().getClassLoader());
Resource resource = resourceLoader.getResource(DEFAULT_LOCATION);
if (resource == null) {
return null;
}
return new MapPropertySource("myJson", mapPropertySource(resource));
}
/**
* Resource转Map
*
* @param resource
* @return
*/
private Map<String, Object> mapPropertySource(Resource resource) {
Map<String, Object> result = new HashMap<>();
// 获取json格式的Map
Map<String, Object> fileMap = JSONObject.parseObject(readFile(resource), Map.class);
// 组装嵌套json
processorMap("", result, fileMap);
return result;
}
private void processorMap(String prefix, Map<String, Object> result, Map<String, Object> fileMap) {
if (prefix.length() > 0) {
prefix += ".";
}
for (Map.Entry<String, Object> entrySet : fileMap.entrySet()) {
if (entrySet.getValue() instanceof Map) {
processorMap(prefix + entrySet.getKey(), result, (Map<String, Object>) entrySet.getValue());
} else {
result.put(prefix + entrySet.getKey(), entrySet.getValue());
}
}
}
/**
* JSON格式
*
* @param resource
* @return
*/
private String readFile(Resource resource) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(resource.getFile());
String str = "";
byte[] readByte = new byte[1024];
int length;
while ((length = fileInputStream.read(readByte)) > 0) {
str += new String(readByte, 0, length, "UTF-8");
}
return str;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
spring读取所有PropertySourceLocator的方式是基于SPI机制的,所以我们需要在classpath:META-INF/spring.factories定义org.springframework.cloud.bootstrap.BootstrapConfiguration,spring才能读取到我们自定义的配置JsonPropertySourceLocator
所以我们在resources下创建META-INF/spring.factories,定义以下内容org.springframework.cloud.bootstrap.BootstrapConfiguration=com.example.demo.cloud.sourceloader.JsonPropertySourceLocator
启动springboot,即可使用@Value读取我们的配置了。
扩展
使用这种方式非常灵活,只要在locate方法最后返回一个MapPropertySource对象即可,至于我们如何获取属性,这些我们都可以自己控制,例如我们实现从数据库读取配置来组装MapPropertySource,或者可以实现远程配置中心功能