spring-cloud-alibaba-nacos config import不支持profile以及multiple configurations

236 阅读1分钟

spring-cloud-alibaba-nacos config import不支持profile以及multiple configurations

spring-cloud-starter-alibaba-nacos-config并不支持profile以及multiple configurations, 如果需要可以考虑自行扩展实现该功能

以下为spring-boot2的示例,spring-boot3大同小异

扩展NacosConfigDataLocationResolver

package com.xxx.config.configdata;

import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.cloud.nacos.configdata.NacosConfigDataLocationResolver;
import com.alibaba.cloud.nacos.configdata.NacosConfigDataResource;
import org.apache.commons.logging.Log;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.context.config.*;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.util.ObjectUtils;

import java.util.*;

public class SupportProfileConfigDataLocationResolver extends NacosConfigDataLocationResolver {
    private final Log log;
    private static final String GROUP = "group";
    private static final String REFRESH_ENABLED = "refreshEnabled";
    private static final String IGNORE_PROFILE = "ignoreProfile";
    private static final String PREFERENCE = "preference";

    public SupportProfileConfigDataLocationResolver(DeferredLogFactory logFactory) {
        super(logFactory);
        this.log = logFactory.getLog(getClass());
    }

    @Override
    public List<NacosConfigDataResource> resolve(ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location) throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException {
        NacosConfigProperties properties = loadProperties(resolverContext);
        registerBean(properties, resolverContext);
        List<NacosConfigDataResource> result = new ArrayList<>();
        for (ConfigDataLocation configDataLocation : location.split()) {
            result.add(loadConfigDataResource(configDataLocation, null, properties));
        }
        return result;
    }

    @Override
    public List<NacosConfigDataResource> resolveProfileSpecific(ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, Profiles profiles) throws ConfigDataLocationNotFoundException {
        NacosConfigProperties properties = loadProperties(resolverContext);
        registerBean(properties, resolverContext);
        List<NacosConfigDataResource> result = new ArrayList<>();
        for (ConfigDataLocation configDataLocation : location.split()) {
            Map<String, String> queryMap = getQueryMap(configDataLocation.getValue());
            if (Boolean.parseBoolean(queryMap.getOrDefault(IGNORE_PROFILE, "false"))) {
                continue;
            }
            for (String profile : profiles) {
                result.add(loadConfigDataResource(getProfileConfigDataLocation(configDataLocation, profile),
                        profiles, properties));
            }
        }
        return result;
    }

    private void registerBean(NacosConfigProperties properties,
                              ConfigDataLocationResolverContext resolverContext) {
        ConfigurableBootstrapContext bootstrapContext = resolverContext
                .getBootstrapContext();
        bootstrapContext.registerIfAbsent(NacosConfigProperties.class,
                BootstrapRegistry.InstanceSupplier.of(properties));
        bootstrapContext.registerIfAbsent(NacosConfigManager.class,
                BootstrapRegistry.InstanceSupplier.from(() -> new NacosConfigManager(properties)));

    }

    ConfigDataLocation getProfileConfigDataLocation(ConfigDataLocation configDataLocation, String profile) {
        StringBuilder profileResourceLocation = new StringBuilder(
                configDataLocation.isOptional() ? ConfigDataLocation.OPTIONAL_PREFIX : "");
        String resourceLocation = configDataLocation.getValue();
        int paramIndex = resourceLocation.indexOf('?') < 0 ? resourceLocation.length() : resourceLocation.indexOf('?');
        int extensionIndex = resourceLocation.lastIndexOf('.', paramIndex);
        profileResourceLocation.append(resourceLocation, 0, extensionIndex > 0 ? extensionIndex : paramIndex);
        profileResourceLocation.append('-').append(profile);
        profileResourceLocation.append(resourceLocation.substring(extensionIndex > 0 ? extensionIndex : paramIndex));
        return ConfigDataLocation.of(profileResourceLocation.toString());
    }

    private NacosConfigDataResource loadConfigDataResource(
            ConfigDataLocation location, Profiles profiles,
            NacosConfigProperties properties) {
        String resourceLocation = location.getNonPrefixedValue(getPrefix());
        int paramIndex = resourceLocation.indexOf('?') < 0 ? resourceLocation.length() : resourceLocation.indexOf('?');
        Map<String, String> queryMap = getQueryMap(resourceLocation);
        int extensionIndex = resourceLocation.lastIndexOf('.', paramIndex);
        String dataId = resourceLocation.substring(0, paramIndex);
        String suffix = extensionIndex > 0 ? resourceLocation.substring(extensionIndex, paramIndex) : null;
        return new NacosConfigDataResource(properties,
                location.isOptional(), profiles, log,
                new NacosConfigDataResource.NacosItemConfig().setGroup(queryMap.getOrDefault(GROUP, properties.getGroup()))
                        .setDataId(dataId).setSuffix(ObjectUtils.isEmpty(suffix) ? properties.getFileExtension() : suffix)
                        .setRefreshEnabled(queryMap.containsKey(REFRESH_ENABLED) ? Boolean.parseBoolean(queryMap.get(REFRESH_ENABLED)) : properties.isRefreshEnabled())
                        .setPreference(queryMap.get(PREFERENCE)));
    }

    private Map<String, String> getQueryMap(String resourceLocation) {
        if (resourceLocation.indexOf('?') < 0) {
            return Collections.emptyMap();
        }
        String query = resourceLocation.substring(resourceLocation.indexOf('?') + 1);
        Map<String, String> result = new HashMap<>(4);
        for (String entry : query.split("&")) {
            String[] kv = entry.split("=");
            if (kv.length == 2) {
                result.put(kv[0], kv[1]);
            }
        }
        return result;
    }

    @Override
    public int getOrder() {
        return -2;
    }
}

新增spring.factories

org.springframework.boot.context.config.ConfigDataLocationResolver=\
com.xxx.config.configdata.SidecarConfigDataLocationResolver