Nacos当前命名空间下的配置文件需要跨命名空间读取其他配置文件的内容。可以先通过Nacos提供的API接口获取配置文件内容,然后解析数据将其放入环境的PropertySource中。
<!-- Nacos依赖包 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.3.0</version>
</dependency>
@Order(Ordered.HIGHEST_PRECEDENCE)
public class NacosEnvironmentPostProcessor implements EnvironmentPostProcessor {
private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";
private static final String[] dataIds = new String[]{"db-sample.yml"};
private static final String LOGIN_URL = "http://$host/nacos/v1/auth/users/login";
private static final String CONFIGS_URL = "http://$host/nacos/v1/cs/configs?dataId=&group=&appName=&config_tags=&pageNo=1&pageSize=100&tenant=$tenant&search=blur&accessToken=$accessToken";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
if (environment instanceof StandardServletEnvironment || environment instanceof StandardReactiveWebEnvironment) {
return;
}
addPropertySource(environment);
}
private void addPropertySource(ConfigurableEnvironment environment) {
Map<String, Object> systemEnvironment = environment.getSystemEnvironment();
Object namespaceIdObj = systemEnvironment.get("NACOS_NAMESPACE");
if (null == namespaceIdObj) {
return;
}
String host = String.valueOf(systemEnvironment.get("NACOS_HOST"));
String username = String.valueOf(systemEnvironment.get("NACOS_USERNAME"));
String password = String.valueOf(systemEnvironment.get("NACOS_PASSWORD"));
String group = String.valueOf(systemEnvironment.get("NACOS_GROUP"));
String namespaceId = String.valueOf(namespaceIdObj);
log.info("{} {} {} {} {}", host, username, password, group, namespaceId);
processV2(environment, host, username, password, namespaceId);
}
private void processV1(ConfigurableEnvironment environment, String host, String username, String password,
String namespaceId, String group) {
NacosConfigProperties nacosConfigProperties = new NacosConfigProperties();
nacosConfigProperties.setEnvironment(new StandardEnvironment());
nacosConfigProperties.setServerAddr(host);
nacosConfigProperties.setUsername(username);
nacosConfigProperties.setPassword(password);
nacosConfigProperties.setNamespace(namespaceId);
nacosConfigProperties.setGroup(group);
ConfigService configService = null;
try {
configService = NacosFactory.createConfigService(nacosConfigProperties.assembleConfigServiceProperties());
} catch (NacosException e) {
log.error(e.getMessage(), e);
}
if (null == configService) {
return;
}
Properties properties = new Properties();
for (String dataId : dataIds) {
addProperties(dataId, getPropertySources(configService, dataId, group), properties);
}
environment.getPropertySources().addFirst(new PropertiesPropertySource(NACOS_PROPERTY_SOURCE_NAME, properties));
}
private List<PropertySource<?>> getPropertySources(ConfigService configService, String dataId, String group) {
List<PropertySource<?>> propertySources = null;
try {
String config = configService.getConfig(dataId, group, 10000);
log.info("{} {} config {}", dataId, group, config);
propertySources = NacosDataParserHandler.getInstance().parseNacosData(dataId, config, null);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return propertySources;
}
private void processV2(ConfigurableEnvironment environment, String host, String username, String password,
String namespaceId) {
if (null != host && host.contains(",")) {
host = host.split(",")[0];
}
Map<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
String loginResp = HttpClientUtils.sendPost(LOGIN_URL.replace("$host", host), params, "UTF-8");
log.info("login response {}", loginResp);
LoginDTO loginDTO = JsonUtils.json(loginResp, LoginDTO.class);
if (null == loginDTO) {
return;
}
String configsResp = HttpClientUtils.sendGet(CONFIGS_URL.replace("$host", host)
.replace("$tenant", namespaceId).replace("$accessToken", loginDTO.getAccessToken()), "UTF-8");
ConfigDTO configDTO = JsonUtils.json(configsResp, ConfigDTO.class);
if (null == configDTO) {
return;
}
List<ConfigDTO.Item> pageItems = configDTO.getPageItems();
if (null == pageItems) {
return;
}
Properties properties = new Properties();
pageItems.forEach(item -> addProperties(item.getDataId(), getPropertySources(item), properties));
environment.getPropertySources().addFirst(new PropertiesPropertySource(NACOS_PROPERTY_SOURCE_NAME, properties));
}
private List<PropertySource<?>> getPropertySources(ConfigDTO.Item item) {
List<PropertySource<?>> propertySources = null;
try {
propertySources = NacosDataParserHandler.getInstance().parseNacosData(item.getDataId(), item.getContent(), null);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return propertySources;
}
private void addProperties(String dataId, List<PropertySource<?>> propertySources, Properties properties) {
if (null == propertySources || propertySources.isEmpty()) {
return;
}
propertySources.forEach(propertySource -> {
Object source = propertySource.getSource();
if (source instanceof Map) {
Map<String, Object> map = (Map) source;
map.forEach((key, value) -> {
if (!key.equals("spring.application.name") && !key.startsWith("server")) {
int i = dataId.lastIndexOf(".");
if (i != -1) {
properties.setProperty(dataId.substring(0, i + 1) + key, String.valueOf(value));
}
}
});
}
});
}
}