假如有一个需求: 初始化要加载很多的JSON 格式的文件, 到Spring容器中,spring 上下文。 直接使用@value 注解获取一些属性值。 这种就需要自己来自定义解析器, springboot 默认支持application.properties 和 application.yml ,这里我们要自定义application.json , 解析json 文件, 变成kv的map 形式。 再用@value 注解获取。
我们看一下propertySourceLoad 的源码
第一个方法返回的是后缀是什么格式的。
第二个是加载文件变成 PropertySource 。
第三个是要返回MapPropertySource 变成k,v 形式 才能被 @Value 识别。
第四最后在加入META-INF/spring.factories里面,
org.springframework.boot.env.PropertySourceLoader =xxxx
指定自定义的ProPertySourceLoader
代码
/**
* 自定义json 配置文件解析器 ,可以使用@Value 的注解
*/
public class JsonPropertySourceLoader implements PropertySourceLoader {
/**
* 返回支持的文件扩展名, 目前只支持json
* @return
*/
@Override
public String[] getFileExtensions() {
return new String[]{"json"};
}
/**
* 把json 转成key value 形式
* @param name
* @param resource
* @return
* @throws IOException
*/
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
return Collections.singletonList(new MapPropertySource(name, 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;
}
}