【Java】 解决OriginTrackedValue incompatible with String 问题

问题

在Springboot项目读取yaml文件时出现类型转换错误,如下所示:

org.springframework.boot.origin.OriginTrackedValue incompatible with java.lang.String

分析

现遇到了一个场景需要动态读取配置信息,于是打算通过Environment去获取环境变量中的application配置:

PropertySource<?> activeSource = ((StandardServletEnvironment)env).getPropertySources().get("applicationConfig: [classpath:/application-" + activeProfile + ".yml]");
Map<String, String> activeAppMap =(Map<String, String>)activeSource.getSource();

如上代码所示,我们是可以通过Map<String,String>去接住PropertySource类型的Source对象。因为activeSource.getSource()返回的是一个Object对象。但这样的话在循环activeAppMap获取Key、Value时将会出错。通过源码得知activeSource.getSource()获取到的虽然是一个Object对象,但实际上它是一个LinkedHashMap,而里面的Value是一个OriginTrackedValue对象。这个OriginTrackedValue对象是通过origin去存储对象的,因此只能够通过origin.getValue()方法才能够获取到真正的值。

所以真正getSource方法返回是LinkedHashMap<String,OriginTrackedValue>类型,而我们通过Map去做向上转型也是可以的。整体代码如下所示:

private Map<String, String> getYmlConfig(Environment env, String prefix) 
{
    
    
        Map<String, String> reMap = new HashMap<>();
        Map<String, OriginTrackedValue> appMap = new LinkedHashMap<>();
        String[] activeProfiles = env.getActiveProfiles();
        if (activeProfiles.length > 0) {
    
    
            for (String activeProfile : activeProfiles) {
    
    
                PropertySource<?> activeSource = 
((StandardServletEnvironment)env).getPropertySources().get("applicationConfig:[classpath:/application-" + activeProfile + ".yml]");
                Map<String, OriginTrackedValue> activeAppMap =(Map<String, 
OriginTrackedValue>)activeSource.getSource();
                if (null != activeAppMap && !activeAppMap.isEmpty()) {
    
    
                    appMap.putAll(activeAppMap);
                }
            }
        }
        PropertySource<?> source = 
((StandardServletEnvironment)env).getPropertySources().get("applicationConfig: [classpath:/config/application.yml]");
        Map<String, OriginTrackedValue> localAppMap = (Map<String, 
OriginTrackedValue>)source.getSource();
        if (null != localAppMap && !localAppMap.isEmpty()) {
    
    
            appMap.putAll(localAppMap);
        }
        if (null != appMap && !appMap.isEmpty()) {
    
    
            appMap.forEach((k, v) -> {
    
    
                if (k.contains(prefix)) {
    
    
                    reMap.put(k, String.valueOf(v.getValue()));
                }
            });
        }
        return reMap;
    }

猜你喜欢

转载自blog.csdn.net/kida_yuan/article/details/129535419