Spring Boot 除 xml/yml 外,利用 SPI 支持对 json 配置文件的解析
z 2022-02-17
SPI
继上一篇JDK/Dubbo/Spring 三种SPI机制解析之后,今天就在 Spring Boot 中,利用 SPI 支持对 json 配置文件的解析。
SpringBoot 的配置文件内置支持 properties、xml、yml、yaml 几种格式,其中 properties 和 xml 对应的Loader类为 PropertiesPropertySourceLoader ,yml和yaml 对应的Loader类为 YamlPropertySourceLoader。
了解了 Spring SPI 机制后,观察这2个类可以发现,都实现自接口 PropertySourceLoader 。所以我们要新增支持别的格式的配置文件,就可以通过实现接口 PropertySourceLoader 来实现了。
参照 PropertiesPropertySourceLoader , 下面实现了一个 json 格式的配置文件 Loader类:
/**
* JSON格式配置文件加载器
*/
public class JsonPropertySourceLoader implements PropertySourceLoader {
public String[] getFileExtensions() {
// 配置文件格式(扩展名)
return new String[] { "json" };
}
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
if (resource == null || !resource.exists()) {
return Collections.emptyList();
}
Map<String, Object> map = JSON.parseObject(resource.getInputStream(), Map.class);
Map<String, Object> resutltMap = new HashMap<>();
// 将json转为键值对
parseMap("", resutltMap, map);
return Collections.singletonList(return new MapPropertySource(name, result));
}
private void parseMap(String prefix, Map<String, Object> result, Map<String, Object> map) {
if (prefix.length() > 0) {
prefix += ".";
}
for (Map.Entry<String, Object> entrySet : map.entrySet()) {
if (entrySet.getValue() instanceof Map) {
nestMap(prefix + entrySet.getKey(), result, (Map<String, Object>) entrySet.getValue());
} else {
result.put(prefix + entrySet.getKey().toString(), entrySet.getValue());
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
然后在 src/main/resources 中创建 META-INF/spring.factories 文件,内容为:
org.springframework.boot.env.PropertySourceLoader=\
com.shanhy.sboot.property.JsonPropertySourceLoader
1
2
2
创建测试的配置文件 application.json
{
"custom": {
"property": {
"message": "测试数据"
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
创建验证结果的 HelloController.java
@RestController
public class HelloController {
@Value("${custom.property.message}")
private Object customProperty;
@RequestMapping("/test")
public Object test() {
return customProperty;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
启动工程服务,浏览器访问 http://localhost:8080/test 即可查看输出的结果为 “测试数据”;
打赏一下
「真诚赞赏,手留余香」
# 打赏记录
打赏者 | 打助金额 (元) | 支付方式 | 时间 | 备注 |
---|---|---|---|---|
John | 12 | 微信 | 2020-06-09 | tip of you |
艾斯 | 32 | 支付宝 | 2020-07-11 | 火拳赞赏 |
HickSalmon | 15 | 微信 | 2020-09-21 | 有赏交流 |