Nacos启动配置
@EnableConfigurationProperties(NacosProperties.class)
public class NacosConfiguration {
/**
* register configService in spring ioc.
*
* @param nacosProp the nacos configuration
* @return ConfigService {@linkplain ConfigService}
* @throws Exception the exception
*/
@Bean
@ConditionalOnMissingBean(ConfigService.class)
public ConfigService nacosConfigService(final NacosProperties nacosProp) throws Exception {
Properties properties = new Properties();
if (nacosProp.getAcm() != null && nacosProp.getAcm().isEnabled()) {
// Use aliyun ACM service
properties.put(PropertyKeyConst.ENDPOINT, nacosProp.getAcm().getEndpoint());
properties.put(PropertyKeyConst.NAMESPACE, nacosProp.getAcm().getNamespace());
// Use subaccount ACM administrative authority
properties.put(PropertyKeyConst.ACCESS_KEY, nacosProp.getAcm().getAccessKey());
properties.put(PropertyKeyConst.SECRET_KEY, nacosProp.getAcm().getSecretKey());
} else {
properties.put(PropertyKeyConst.SERVER_ADDR, nacosProp.getUrl());
properties.put(PropertyKeyConst.NAMESPACE, nacosProp.getNamespace());
}
return NacosFactory.createConfigService(properties);
}
}
数据变动配置
public class NacosDataChangedListener implements DataChangedListener {
private static final ConcurrentMap<String, PluginData> PLUGIN_MAP = Maps.newConcurrentMap();
private static final ConcurrentMap<String, List<SelectorData>> SELECTOR_MAP = Maps.newConcurrentMap();
private static final ConcurrentMap<String, List<RuleData>> RULE_MAP = Maps.newConcurrentMap();
private static final ConcurrentMap<String, AppAuthData> AUTH_MAP = Maps.newConcurrentMap();
private static final ConcurrentMap<String, MetaData> META_DATA = Maps.newConcurrentMap();
private static final Comparator<SelectorData> SELECTOR_DATA_COMPARATOR = Comparator.comparing(SelectorData::getSort);
private static final Comparator<RuleData> RULE_DATA_COMPARATOR = Comparator.comparing(RuleData::getSort);
private static final String GROUP = "DEFAULT_GROUP";
private static final String PLUGIN_DATA_ID = "soul.plugin.json";
private static final String SELECTOR_DATA_ID = "soul.selector.json";
private static final String RULE_DATA_ID = "soul.rule.json";
private static final String AUTH_DATA_ID = "soul.auth.json";
private static final String META_DATA_ID = "soul.meta.json";
private static final String EMPTY_CONFIG_DEFAULT_VALUE = "{}";
private final ConfigService configService;
public NacosDataChangedListener(final ConfigService configService) {
this.configService = configService;
}
private void updateAuthMap(final String configInfo) {
JsonObject jo = GsonUtils.getInstance().fromJson(configInfo, JsonObject.class);
Set<String> set = new HashSet<>(AUTH_MAP.keySet());
for (Entry<String, JsonElement> e : jo.entrySet()) {
set.remove(e.getKey());
AUTH_MAP.put(e.getKey(), GsonUtils.getInstance().fromJson(e.getValue(), AppAuthData.class));
}
AUTH_MAP.keySet().removeAll(set);
}
private void updatePluginMap(final String configInfo) {
JsonObject jo = GsonUtils.getInstance().fromJson(configInfo, JsonObject.class);
Set<String> set = new HashSet<>(PLUGIN_MAP.keySet());
for (Entry<String, JsonElement> e : jo.entrySet()) {
set.remove(e.getKey());
PLUGIN_MAP.put(e.getKey(), GsonUtils.getInstance().fromJson(e.getValue(), PluginData.class));
}
PLUGIN_MAP.keySet().removeAll(set);
}
private void updateSelectorMap(final String configInfo) {
JsonObject jo = GsonUtils.getInstance().fromJson(configInfo, JsonObject.class);
Set<String> set = new HashSet<>(SELECTOR_MAP.keySet());
for (Entry<String, JsonElement> e : jo.entrySet()) {
set.remove(e.getKey());
List<SelectorData> ls = new ArrayList<>();
e.getValue().getAsJsonArray().forEach(je -> ls.add(GsonUtils.getInstance().fromJson(je, SelectorData.class)));
SELECTOR_MAP.put(e.getKey(), ls);
}
SELECTOR_MAP.keySet().removeAll(set);
}
private void updateMetaDataMap(final String configInfo) {
JsonObject jo = GsonUtils.getInstance().fromJson(configInfo, JsonObject.class);
Set<String> set = new HashSet<>(META_DATA.keySet());
for (Entry<String, JsonElement> e : jo.entrySet()) {
set.remove(e.getKey());
META_DATA.put(e.getKey(), GsonUtils.getInstance().fromJson(e.getValue(), MetaData.class));
}
META_DATA.keySet().removeAll(set);
}
private void updateRuleMap(final String configInfo) {
JsonObject jo = GsonUtils.getInstance().fromJson(configInfo, JsonObject.class);
Set<String> set = new HashSet<>(RULE_MAP.keySet());
for (Entry<String, JsonElement> e : jo.entrySet()) {
set.remove(e.getKey());
List<RuleData> ls = new ArrayList<>();
e.getValue().getAsJsonArray().forEach(je -> ls.add(GsonUtils.getInstance().fromJson(je, RuleData.class)));
RULE_MAP.put(e.getKey(), ls);
}
RULE_MAP.keySet().removeAll(set);
}
@SneakyThrows
private String getConfig(final String dataId) {
String config = configService.getConfig(dataId, GROUP, 6000);
return StringUtils.hasLength(config) ? config : EMPTY_CONFIG_DEFAULT_VALUE;
}
@SneakyThrows
private void publishConfig(final String dataId, final Object data) {
configService.publishConfig(dataId, GROUP, GsonUtils.getInstance().toJson(data));
}
@Override
@SneakyThrows
public void onAppAuthChanged(final List<AppAuthData> changed, final DataEventTypeEnum eventType) {
updateAuthMap(getConfig(AUTH_DATA_ID));
switch (eventType) {
case DELETE:
changed.forEach(appAuth -> AUTH_MAP.remove(appAuth.getAppKey()));
break;
case REFRESH:
case MYSELF:
Set<String> set = new HashSet<>(AUTH_MAP.keySet());
changed.forEach(appAuth -> {
set.remove(appAuth.getAppKey());
AUTH_MAP.put(appAuth.getAppKey(), appAuth);
});
AUTH_MAP.keySet().removeAll(set);
break;
default:
changed.forEach(appAuth -> AUTH_MAP.put(appAuth.getAppKey(), appAuth));
break;
}
publishConfig(AUTH_DATA_ID, AUTH_MAP);
}
@Override
public void onPluginChanged(final List<PluginData> changed, final DataEventTypeEnum eventType) {
updatePluginMap(getConfig(PLUGIN_DATA_ID));
switch (eventType) {
case DELETE:
changed.forEach(plugin -> PLUGIN_MAP.remove(plugin.getName()));
break;
case REFRESH:
case MYSELF:
Set<String> set = new HashSet<>(PLUGIN_MAP.keySet());
changed.forEach(plugin -> {
set.remove(plugin.getName());
PLUGIN_MAP.put(plugin.getName(), plugin);
});
PLUGIN_MAP.keySet().removeAll(set);
break;
default:
changed.forEach(plugin -> PLUGIN_MAP.put(plugin.getName(), plugin));
break;
}
publishConfig(PLUGIN_DATA_ID, PLUGIN_MAP);
}
@Override
public void onSelectorChanged(final List<SelectorData> changed, final DataEventTypeEnum eventType) {
updateSelectorMap(getConfig(SELECTOR_DATA_ID));
switch (eventType) {
case DELETE:
changed.forEach(selector -> {
List<SelectorData> ls = SELECTOR_MAP
.getOrDefault(selector.getPluginName(), new ArrayList<>())
.stream()
.filter(s -> !s.getId().equals(selector.getId()))
.sorted(SELECTOR_DATA_COMPARATOR)
.collect(Collectors.toList());
SELECTOR_MAP.put(selector.getPluginName(), ls);
});
break;
case REFRESH:
case MYSELF:
Set<String> set = new HashSet<>(SELECTOR_MAP.keySet());
changed.forEach(selector -> {
set.remove(selector.getPluginName());
List<SelectorData> ls = SELECTOR_MAP
.getOrDefault(selector.getPluginName(), new ArrayList<>())
.stream()
.sorted(SELECTOR_DATA_COMPARATOR)
.collect(Collectors.toList());
SELECTOR_MAP.put(selector.getPluginName(), ls);
});
SELECTOR_MAP.keySet().removeAll(set);
break;
default:
changed.forEach(selector -> {
List<SelectorData> ls = SELECTOR_MAP
.getOrDefault(selector.getPluginName(), new ArrayList<>())
.stream()
.filter(s -> !s.getId().equals(selector.getId()))
.sorted(SELECTOR_DATA_COMPARATOR)
.collect(Collectors.toList());
ls.add(selector);
SELECTOR_MAP.put(selector.getPluginName(), ls);
});
break;
}
publishConfig(SELECTOR_DATA_ID, SELECTOR_MAP);
}
@Override
public void onMetaDataChanged(final List<MetaData> changed, final DataEventTypeEnum eventType) {
updateMetaDataMap(getConfig(META_DATA_ID));
switch (eventType) {
case DELETE:
changed.forEach(meta -> META_DATA.remove(meta.getPath()));
break;
case REFRESH:
case MYSELF:
Set<String> set = new HashSet<>(META_DATA.keySet());
changed.forEach(meta -> {
set.remove(meta.getPath());
META_DATA.put(meta.getPath(), meta);
});
META_DATA.keySet().removeAll(set);
break;
default:
changed.forEach(meta -> {
META_DATA
.values()
.stream()
.filter(md -> Objects.equals(md.getId(), meta.getId()))
.forEach(md -> META_DATA.remove(md.getPath()));
META_DATA.put(meta.getPath(), meta);
});
break;
}
publishConfig(META_DATA_ID, META_DATA);
}
@Override
public void onRuleChanged(final List<RuleData> changed, final DataEventTypeEnum eventType) {
updateRuleMap(getConfig(RULE_DATA_ID));
switch (eventType) {
case DELETE:
changed.forEach(rule -> {
List<RuleData> ls = RULE_MAP
.getOrDefault(rule.getSelectorId(), new ArrayList<>())
.stream()
.filter(s -> !s.getId().equals(rule.getId()))
.sorted(RULE_DATA_COMPARATOR)
.collect(Collectors.toList());
RULE_MAP.put(rule.getSelectorId(), ls);
});
break;
case REFRESH:
case MYSELF:
Set<String> set = new HashSet<>(RULE_MAP.keySet());
changed.forEach(rule -> {
set.remove(rule.getSelectorId());
List<RuleData> ls = RULE_MAP
.getOrDefault(rule.getSelectorId(), new ArrayList<>())
.stream()
.sorted(RULE_DATA_COMPARATOR)
.collect(Collectors.toList());
RULE_MAP.put(rule.getSelectorId(), ls);
});
RULE_MAP.keySet().removeAll(set);
break;
default:
changed.forEach(rule -> {
List<RuleData> ls = RULE_MAP
.getOrDefault(rule.getSelectorId(), new ArrayList<>())
.stream()
.filter(s -> !s.getId().equals(rule.getSelectorId()))
.sorted(RULE_DATA_COMPARATOR)
.collect(Collectors.toList());
ls.add(rule);
RULE_MAP.put(rule.getSelectorId(), ls);
});
break;
}
publishConfig(RULE_DATA_ID, RULE_MAP);
}
}
主要逻辑就是,当数据修改后,重新刷新数据,主要采用Switch提升代码可读性,更加优雅;