----初始化项目

This commit is contained in:
2025-09-19 20:49:14 +08:00
parent b345d2828d
commit df7765c400
2867 changed files with 359313 additions and 89 deletions

41
plugin/config/pom.xml Normal file
View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 1999-2021 Alibaba Group Holding Ltd.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-plugin</artifactId>
<groupId>com.alibaba.nacos</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-config-plugin</artifactId>
<name>nacos-config-plugin ${project.version}</name>
<url>http://nacos.io</url>
<description>Nacos config plugin pom.xml file</description>
<dependencies>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,149 @@
/*
* Copyright 1999-2022 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
import com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Collection;
import java.util.Optional;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Comparator;
/**
* All config change plugin manager.
*
* @author liyunfei
*/
public class ConfigChangePluginManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChangePluginManager.class);
private static final Integer PLUGIN_SERVICE_COUNT = 4;
private static final Integer POINT_CUT_TYPE_COUNT = ConfigChangePointCutTypes.values().length;
/**
* The relationship of serviceType and {@link ConfigChangePluginService} ,default capacity is the count of plugin
* service.
*/
private static final Map<String, ConfigChangePluginService> CONFIG_CHANGE_PLUGIN_SERVICE_MAP = new ConcurrentHashMap<>(
PLUGIN_SERVICE_COUNT);
/**
* The relationship of config change pointcut type and the list of {@link ConfigChangePluginService} will pointcut
* it, default capacity is the count of pointcutTypes.
*/
private static final Map<ConfigChangePointCutTypes, List<ConfigChangePluginService>> CONFIG_CHANGE_PLUGIN_SERVICES_MAP = new ConcurrentHashMap<>(
POINT_CUT_TYPE_COUNT);
private static final ConfigChangePluginManager INSTANCE = new ConfigChangePluginManager();
private ConfigChangePluginManager() {
loadConfigChangeServices();
}
/**
* Load all config change plugin services by spi.
*/
private static void loadConfigChangeServices() {
Collection<ConfigChangePluginService> configChangePluginServices = NacosServiceLoader
.load(ConfigChangePluginService.class);
// load all config change plugin by spi
for (ConfigChangePluginService each : configChangePluginServices) {
if (StringUtils.isEmpty(each.getServiceType())) {
LOGGER.warn("[ConfigChangePluginManager] Load {}({}) ConfigChangeServiceName(null/empty) fail. "
+ "Please Add the Plugin Service ConfigChangeServiceName to resolve.",
each.getClass().getName(), each.getClass());
continue;
}
CONFIG_CHANGE_PLUGIN_SERVICE_MAP.put(each.getServiceType(), each);
LOGGER.info("[ConfigChangePluginManager] Load {}({}) ConfigChangeServiceName({}) successfully.",
each.getClass().getName(), each.getClass(), each.getServiceType());
// map the relationship of pointcut and plugin service
addPluginServiceByPointCut(each);
}
// sort plugin service
sortPluginServiceByPointCut();
}
public static ConfigChangePluginManager getInstance() {
return INSTANCE;
}
/**
* Dynamic get any pluginServiceImpl.
*
* @param serviceType plugin service type.
* @return
*/
public Optional<ConfigChangePluginService> findPluginServiceImpl(String serviceType) {
return Optional.ofNullable(CONFIG_CHANGE_PLUGIN_SERVICE_MAP.get(serviceType));
}
/**
* Dynamic add new ConfigChangeService.
*
* @param configChangePluginService ConfigChangeService.
* @return
*/
public static synchronized boolean join(ConfigChangePluginService configChangePluginService) {
CONFIG_CHANGE_PLUGIN_SERVICE_MAP
.putIfAbsent(configChangePluginService.getServiceType(), configChangePluginService);
addPluginServiceByPointCut(configChangePluginService);
return true;
}
/**
* Get the plugin service queue of the pointcut method.
*
* @param pointcutName pointcut method name,detail see {@link ConfigChangePointCutTypes}.
* @return
*/
public static List<ConfigChangePluginService> findPluginServicesByPointcut(
ConfigChangePointCutTypes pointcutName) {
return CONFIG_CHANGE_PLUGIN_SERVICES_MAP.getOrDefault(pointcutName, new ArrayList<>());
}
private static void addPluginServiceByPointCut(ConfigChangePluginService configChangePluginService) {
ConfigChangePointCutTypes[] pointcutNames = configChangePluginService.pointcutMethodNames();
for (ConfigChangePointCutTypes name : pointcutNames) {
List<ConfigChangePluginService> configChangePluginServiceList = CONFIG_CHANGE_PLUGIN_SERVICES_MAP
.get(name);
if (configChangePluginServiceList == null) {
configChangePluginServiceList = new ArrayList<>(PLUGIN_SERVICE_COUNT);
}
configChangePluginServiceList.add(configChangePluginService);
CONFIG_CHANGE_PLUGIN_SERVICES_MAP.put(name, configChangePluginServiceList);
}
}
private static void sortPluginServiceByPointCut() {
CONFIG_CHANGE_PLUGIN_SERVICES_MAP.forEach((type, pluginServices) -> {
List<ConfigChangePluginService> sortedList = new ArrayList<>(pluginServices);
sortedList.sort(Comparator.comparingInt(ConfigChangePluginService::getOrder));
CONFIG_CHANGE_PLUGIN_SERVICES_MAP.put(type, sortedList);
});
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config.constants;
/**
* Config change plugin service constants.
*
* @author liyunfei
*/
public class ConfigChangeConstants {
public static final String NACOS_CORE_CONFIG_PLUGIN_PREFIX = "nacos.core.config.plugin.";
public static final String PLUGIN_PROPERTIES = "pluginProperties";
/**
* The actual config method args.
*/
public static final String ORIGINAL_ARGS = "originalArgs";
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config.constants;
/**
* ConfigChangeExecuteTypes.
*
* @author liyunfei
*/
public enum ConfigChangeExecuteTypes {
/**
* Execute before pointcut.
*/
EXECUTE_BEFORE_TYPE,
/**
* Execute after pointcut.
*/
EXECUTE_AFTER_TYPE;
public boolean equals(ConfigChangeExecuteTypes configChangeExecuteTypes) {
return this.compareTo(configChangeExecuteTypes) == 0;
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config.constants;
/**
* Config change type depend on the pointcut method.
*
* @author liyunfei
*/
public enum ConfigChangePointCutTypes {
/**
* Publish or update config through http.
*/
PUBLISH_BY_HTTP("publishOrUpdateByHttp"),
/**
* Publish config through rpc.
*/
PUBLISH_BY_RPC("publishOrUpdateByRpc"),
/**
* Remove by id through http.
*/
REMOVE_BY_HTTP("removeSingleByHttp"),
/**
* Remove through rpc.
*/
REMOVE_BY_RPC("removeSingleByRpc"),
/**
* Import config file through http/console.
*/
IMPORT_BY_HTTP("importFileByHttp"),
/**
* Remove by ids through http.
*/
REMOVE_BATCH_HTTP("removeBatchByHttp");
private final String value;
ConfigChangePointCutTypes(String value) {
this.value = value;
}
public String value() {
return value;
}
public boolean equals(ConfigChangePointCutTypes configChangePointCutTypes) {
return this.compareTo(configChangePointCutTypes) == 0;
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config.model;
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
import java.util.HashMap;
/**
* ConfigChangeRequest.
*
* @author liyunfei
*/
public class ConfigChangeRequest {
private ConfigChangePointCutTypes requestType;
private HashMap<String, Object> requestArgs = new HashMap<>(8);
public ConfigChangeRequest(ConfigChangePointCutTypes requestType) {
this.requestType = requestType;
}
public ConfigChangePointCutTypes getRequestType() {
return requestType;
}
public void setArg(String key, Object value) {
requestArgs.putIfAbsent(key, value);
}
public Object getArg(String key) {
return requestArgs.getOrDefault(key, null);
}
public HashMap<String, Object> getRequestArgs() {
return requestArgs;
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config.model;
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
/**
* ConfigChangeResponse.
*
* @author liyunfei
*/
public class ConfigChangeResponse {
private ConfigChangePointCutTypes responseType;
private boolean isSuccess;
private Object retVal;
private String msg;
private Object[] args;
public ConfigChangeResponse(ConfigChangePointCutTypes responseType) {
this.responseType = responseType;
}
public ConfigChangePointCutTypes getResponseType() {
return responseType;
}
public void setResponseType(ConfigChangePointCutTypes responseType) {
this.responseType = responseType;
}
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean success) {
isSuccess = success;
}
public Object getRetVal() {
return retVal;
}
public void setRetVal(Object retVal) {
this.retVal = retVal;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 1999-2022 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config.spi;
import com.alibaba.nacos.plugin.config.constants.ConfigChangeConstants;
import com.alibaba.nacos.plugin.config.constants.ConfigChangeExecuteTypes;
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
import com.alibaba.nacos.plugin.config.model.ConfigChangeRequest;
import com.alibaba.nacos.plugin.config.model.ConfigChangeResponse;
/**
* ConfigChangePluginService.
*
* @author liyunfei
*/
public interface ConfigChangePluginService {
/**
* execute config change plugin service.
*
* @param configChangeRequest ConfigChangeRequest
* @param configChangeResponse ConfigChangeResponse
*/
void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse);
/**
* execute type {@link ConfigChangeExecuteTypes}.
*
* @return type
*/
ConfigChangeExecuteTypes executeType();
/**
* what kind of plugin service,such as webhook,whiteList and other,need keep a way with the constants config of you
* enum in {@link ConfigChangeConstants}.
*
* @return service type
*/
String getServiceType();
/**
* when pointcut the same method,according to order to load plugin service. order is lower,prior is higher.
*
* @return order
*/
int getOrder();
/**
* the ConfigChangeTypes {@link ConfigChangePointCutTypes} of need to pointcut.
*
* <p>
* ConfigChangeTypes mean the relevant pointcut method.
* </p>
*
* @return array of pointcut the methods
*/
ConfigChangePointCutTypes[] pointcutMethodNames();
}

View File

@ -0,0 +1,204 @@
/*
* Copyright 1999-2022 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.plugin.config;
import com.alibaba.nacos.plugin.config.constants.ConfigChangeExecuteTypes;
import com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;
import com.alibaba.nacos.plugin.config.model.ConfigChangeRequest;
import com.alibaba.nacos.plugin.config.model.ConfigChangeResponse;
import com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
/**
* ConfigChangePluginManagerTests.
*
* @author liyunfei
**/
public class ConfigChangePluginManagerTests {
@Test
public void testInstance() {
ConfigChangePluginManager instance = ConfigChangePluginManager.getInstance();
Assert.assertNotNull(instance);
}
@Before
public void initPluginServices() {
ConfigChangePluginManager.join(new ConfigChangePluginService() {
@Override
public void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse) {
// ignore
}
@Override
public ConfigChangeExecuteTypes executeType() {
return ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE;
}
@Override
public String getServiceType() {
return "test1";
}
@Override
public int getOrder() {
return 0;
}
@Override
public ConfigChangePointCutTypes[] pointcutMethodNames() {
return new ConfigChangePointCutTypes[]{ConfigChangePointCutTypes.PUBLISH_BY_HTTP, ConfigChangePointCutTypes.PUBLISH_BY_RPC};
}
});
ConfigChangePluginManager.join(new ConfigChangePluginService() {
@Override
public void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse) {
// ignore
}
@Override
public ConfigChangeExecuteTypes executeType() {
return ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE;
}
@Override
public String getServiceType() {
return "test2";
}
@Override
public int getOrder() {
return 200;
}
@Override
public ConfigChangePointCutTypes[] pointcutMethodNames() {
return new ConfigChangePointCutTypes[]{ConfigChangePointCutTypes.IMPORT_BY_HTTP, ConfigChangePointCutTypes.PUBLISH_BY_RPC};
}
});
ConfigChangePluginManager.join(new ConfigChangePluginService() {
@Override
public void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse) {
// ignore
}
@Override
public ConfigChangeExecuteTypes executeType() {
return ConfigChangeExecuteTypes.EXECUTE_AFTER_TYPE;
}
@Override
public String getServiceType() {
return "test3";
}
@Override
public int getOrder() {
return 400;
}
@Override
public ConfigChangePointCutTypes[] pointcutMethodNames() {
return new ConfigChangePointCutTypes[]{ConfigChangePointCutTypes.IMPORT_BY_HTTP, ConfigChangePointCutTypes.PUBLISH_BY_RPC,
ConfigChangePointCutTypes.REMOVE_BATCH_HTTP, ConfigChangePointCutTypes.REMOVE_BY_RPC,
ConfigChangePointCutTypes.REMOVE_BY_HTTP};
}
});
ConfigChangePluginManager.join(new ConfigChangePluginService() {
@Override
public void execute(ConfigChangeRequest configChangeRequest, ConfigChangeResponse configChangeResponse) {
// ignore
}
@Override
public ConfigChangeExecuteTypes executeType() {
return ConfigChangeExecuteTypes.EXECUTE_AFTER_TYPE;
}
@Override
public String getServiceType() {
return "test4";
}
@Override
public int getOrder() {
return 600;
}
@Override
public ConfigChangePointCutTypes[] pointcutMethodNames() {
return new ConfigChangePointCutTypes[]{ConfigChangePointCutTypes.PUBLISH_BY_HTTP, ConfigChangePointCutTypes.REMOVE_BATCH_HTTP,
ConfigChangePointCutTypes.REMOVE_BY_RPC, ConfigChangePointCutTypes.REMOVE_BY_HTTP};
}
});
}
@Test
public void testFindPluginServiceQueueByPointcut() {
List<ConfigChangePluginService> configChangePluginServices = ConfigChangePluginManager
.findPluginServicesByPointcut(ConfigChangePointCutTypes.PUBLISH_BY_HTTP);
Assert.assertEquals(2, configChangePluginServices.size());
Assert.assertTrue(isSorted(configChangePluginServices));
configChangePluginServices = ConfigChangePluginManager
.findPluginServicesByPointcut(ConfigChangePointCutTypes.PUBLISH_BY_RPC);
Assert.assertEquals(3, configChangePluginServices.size());
Assert.assertTrue(isSorted(configChangePluginServices));
configChangePluginServices = ConfigChangePluginManager
.findPluginServicesByPointcut(ConfigChangePointCutTypes.IMPORT_BY_HTTP);
Assert.assertEquals(2, configChangePluginServices.size());
Assert.assertTrue(isSorted(configChangePluginServices));
configChangePluginServices = ConfigChangePluginManager
.findPluginServicesByPointcut(ConfigChangePointCutTypes.REMOVE_BATCH_HTTP);
Assert.assertEquals(2, configChangePluginServices.size());
Assert.assertTrue(isSorted(configChangePluginServices));
configChangePluginServices = ConfigChangePluginManager
.findPluginServicesByPointcut(ConfigChangePointCutTypes.REMOVE_BY_RPC);
Assert.assertEquals(2, configChangePluginServices.size());
Assert.assertTrue(isSorted(configChangePluginServices));
configChangePluginServices = ConfigChangePluginManager
.findPluginServicesByPointcut(ConfigChangePointCutTypes.REMOVE_BY_HTTP);
Assert.assertEquals(2, configChangePluginServices.size());
Assert.assertTrue(isSorted(configChangePluginServices));
}
@Test
public void testFindPluginServiceByServiceType() {
Optional<ConfigChangePluginService> configChangePluginServiceOptional = ConfigChangePluginManager
.getInstance().findPluginServiceImpl("test1");
Assert.assertTrue(configChangePluginServiceOptional.isPresent());
configChangePluginServiceOptional = ConfigChangePluginManager.getInstance().findPluginServiceImpl("test2");
Assert.assertTrue(configChangePluginServiceOptional.isPresent());
configChangePluginServiceOptional = ConfigChangePluginManager.getInstance().findPluginServiceImpl("test3");
Assert.assertTrue(configChangePluginServiceOptional.isPresent());
configChangePluginServiceOptional = ConfigChangePluginManager.getInstance().findPluginServiceImpl("test4");
Assert.assertTrue(configChangePluginServiceOptional.isPresent());
configChangePluginServiceOptional = ConfigChangePluginManager.getInstance().findPluginServiceImpl("test5");
Assert.assertFalse(configChangePluginServiceOptional.isPresent());
}
private boolean isSorted(List<ConfigChangePluginService> list) {
return IntStream.range(0, list.size() - 1)
.allMatch(i -> list.get(i).getOrder() <= list.get(i + 1).getOrder());
}
}