背景
前端有些内容需要固定传值,如逻辑实体Logic Entity(ODS表位置)对应的命名空间Name Space、业务对象Business Object;默认的展示场景Scene等信息。
每次封装一个controller接口,较为复杂;而这些内容在后端也是通过Nacos配置的,思考可以通过读取Nacos配置,开发一个通用的接口。
思路
注入Nacos的ConfigService,调用String getConfig(String dataId, String group, long timeoutMs),可以获得配置的内容,以字符串呈现;
通过org.yaml.snakeyaml.Yaml解析字符串,便可以取出对应的值;
其中,dataId对应bootstrap.yml配置中的spring.application.name;group对应bootstrap.yml配置中的spring.cloud.nacos.config.group,如:group: ${NACOS_GROUP:DEFAULT_GROUP}
实现
controller
package com.gemenyaofei.xx.metadata.client;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.gemenyaofei.xx.client.base.dto.Result;
import com.gemenyaofei.xx.domain.common.exception.MetadataException;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.yaml.snakeyaml.Yaml;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
/**
* @description:
* @author: gemenyaofei
* @create: 2023/12/19
*/
@RestController
@RequestMapping("/metadata/config")
@Api(tags = "[元数据管理]配置查询")
@Slf4j
public class ConfigQueryController { // todo 可以更新为通过service/工具类方式
@Autowired
private ConfigService configService;
private final String DEFAULT_DATA_ID = "data-xx-platform.yaml";
private final String IGNORE_DATA_ID = "data-xx-platform";
private final String DEFAULT_GROUP = "DEFAULT_GROUP";
private final String DEV_GROUP = "xx";
@Deprecated
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
@ApiOperation(value = "Get/Post方式查询Naocs配置")
public Result<Object> queryConfig(@RequestBody List<String> items) throws NacosException, IOException {
return getObjectResult(items);
}
private Result<Object> getObjectResult(@RequestBody List<String> items) throws NacosException {
Map<String, Object> result = Maps.newHashMap();
String config = Stream.of(configService.getConfig(DEFAULT_DATA_ID, DEV_GROUP, 2000), // 默认dev的
configService.getConfig(IGNORE_DATA_ID, DEV_GROUP, 2000),
configService.getConfig(DEFAULT_DATA_ID, DEFAULT_GROUP, 2000),
configService.getConfig(IGNORE_DATA_ID, DEFAULT_GROUP, 2000)).filter(Objects::nonNull)
.findFirst().orElseThrow(() -> new MetadataException("Nacos配置有问题,请联系后端调整代码"));
Map<String, Object> yamlMap = parseConfig(config);
items.stream().forEach(item -> result.putIfAbsent(item, getValueFromYaml(item, yamlMap)));
return Result.success(result);
}
private static Map<String, Object> parseConfig(String content) {
Yaml yaml = new Yaml();
return yaml.load(content);
}
private static Object getValueFromYaml(String propertyPath, Map<String, Object> yamlMap) {
String[] pathSegments = propertyPath.split("\\.");
Map<String, Object> currentMap = yamlMap;
for (int i = 0; i < pathSegments.length - 1; i++) {
currentMap = (Map<String, Object>) currentMap.get(pathSegments[i]);
}
return handleType(currentMap.get(pathSegments[pathSegments.length - 1]));
}
@Deprecated // 使用Spring mvc的MvcConfig做转换
private static Object handleType(Object o) {
return o;
}
}
调用
POST {{url}}/metadata/config
Content-Type:application/json
Cookie:{{Cookie}}
["assetConfig.er.namespaceId", "assetConfig.er.namespaceCode"]
响应
{
"success": true,
"code": 200,
"message": "操作成功",
"data": {
"assetConfig.er.namespaceCode": "ods",
"assetConfig.er.namespaceId": "1056752105528512512"
}
}