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 | |
| 艾斯 | 32 | 支付宝 | 2020-07-11 | nice | 
| HickSalmon | 15 | 微信 | 2020-09-21 | 有赏交流 | 
- 01
 - 手写Mybatis-01:框架设计与核心概念10-31
 
- 02
 - JetBrains IntelliJ IDEA 个人使用及配置09-22
 
- 03
 - 手写RPC-04:Spring 框架深度集成07-27