This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 7f5c03f10c fix(web): unregister removed ext plugins (#7196)
7f5c03f10c is described below
commit 7f5c03f10cf5bca9cd63bb3e9c697960c9465d88
Author: Liming Deng <[email protected]>
AuthorDate: Thu Sep 24 22:02:28 2026 +0800
fix(web): unregister removed ext plugins (#7196)
Co-authored-by: aias00 <[email protected]>
---
.../shenyu/web/handler/ShenyuWebHandler.java | 15 ++++++++
.../web/loader/ShenyuExtPathPluginJarLoader.java | 42 +++++++++++++++++++---
.../shenyu/web/loader/ShenyuLoaderService.java | 6 ++--
.../shenyu/web/loader/ShenyuPluginClassLoader.java | 17 ++++++++-
.../web/loader/ShenyuPluginClassLoaderHolder.java | 14 ++++++--
.../shenyu/web/handler/ShenyuWebHandlerTest.java | 8 +++++
6 files changed, 92 insertions(+), 10 deletions(-)
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/handler/ShenyuWebHandler.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/handler/ShenyuWebHandler.java
index 3bb84adcfc..d26861764f 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/handler/ShenyuWebHandler.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/handler/ShenyuWebHandler.java
@@ -44,6 +44,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -190,6 +191,20 @@ public final class ShenyuWebHandler implements WebHandler,
ApplicationListener<P
plugins = sortPlugins(newPluginList);
}
+ /**
+ * Remove ext plugins.
+ *
+ * @param pluginNames plugin names
+ */
+ public synchronized void removeExtPlugins(final Set<String> pluginNames) {
+ if (CollectionUtils.isEmpty(pluginNames)) {
+ return;
+ }
+ pluginNames.forEach(pluginName -> LOG.info("shenyu auto remove extends
plugin:{}", pluginName));
+ sourcePlugins.removeIf(plugin -> pluginNames.contains(plugin.named()));
+ plugins = plugins.stream().filter(plugin ->
!pluginNames.contains(plugin.named())).collect(Collectors.toList());
+ }
+
/**
* listen plugin handler event and handle plugin.
*
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuExtPathPluginJarLoader.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuExtPathPluginJarLoader.java
index 0113b9d2e4..1ec0f36a32 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuExtPathPluginJarLoader.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuExtPathPluginJarLoader.java
@@ -41,10 +41,10 @@ public class ShenyuExtPathPluginJarLoader {
* @return the list
* @throws IOException the io exception
*/
- public static synchronized List<PluginJarParser.PluginJar>
loadExtendPlugins(final String path) throws IOException {
+ public static synchronized ExtPluginLoadResult loadExtendPlugins(final
String path) throws IOException {
File[] jarFiles =
ShenyuPluginPathBuilder.getPluginFile(path).listFiles(file ->
file.getName().endsWith(".jar"));
if (Objects.isNull(jarFiles)) {
- return Collections.emptyList();
+ return new ExtPluginLoadResult(Collections.emptyList(),
Collections.emptySet());
}
List<PluginJarParser.PluginJar> uploadPluginJars = new ArrayList<>();
Set<String> currentPaths = new HashSet<>();
@@ -60,11 +60,45 @@ public class ShenyuExtPathPluginJarLoader {
uploadPluginJars.add(uploadPluginJar);
}
Sets.SetView<String> removePluginSet = Sets.difference(pluginJarName,
currentPaths);
+ Set<String> removedPluginNames = new HashSet<>();
for (String removePath : removePluginSet) {
-
ShenyuPluginClassLoaderHolder.getSingleton().removePluginClassLoader(removePath);
+
removedPluginNames.addAll(ShenyuPluginClassLoaderHolder.getSingleton().removePluginClassLoader(removePath));
}
pluginJarName = currentPaths;
- return uploadPluginJars;
+ return new ExtPluginLoadResult(uploadPluginJars, removedPluginNames);
+ }
+
+ /**
+ * Ext plugin load result.
+ */
+ public static final class ExtPluginLoadResult {
+
+ private final List<PluginJarParser.PluginJar> pluginJars;
+
+ private final Set<String> removedPluginNames;
+
+ private ExtPluginLoadResult(final List<PluginJarParser.PluginJar>
pluginJars, final Set<String> removedPluginNames) {
+ this.pluginJars = pluginJars;
+ this.removedPluginNames = removedPluginNames;
+ }
+
+ /**
+ * Get plugin jars.
+ *
+ * @return plugin jars
+ */
+ public List<PluginJarParser.PluginJar> getPluginJars() {
+ return pluginJars;
+ }
+
+ /**
+ * Get removed plugin names.
+ *
+ * @return removed plugin names
+ */
+ public Set<String> getRemovedPluginNames() {
+ return removedPluginNames;
+ }
}
}
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuLoaderService.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuLoaderService.java
index 24b135de66..5776ec3817 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuLoaderService.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuLoaderService.java
@@ -26,6 +26,7 @@ import org.apache.shenyu.plugin.api.ShenyuPlugin;
import org.apache.shenyu.plugin.base.cache.CommonPluginDataSubscriber;
import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
import org.apache.shenyu.web.handler.ShenyuWebHandler;
+import
org.apache.shenyu.web.loader.ShenyuExtPathPluginJarLoader.ExtPluginLoadResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -78,8 +79,9 @@ public class ShenyuLoaderService {
List<ShenyuLoaderResult> plugins = new ArrayList<>();
ShenyuPluginClassLoaderHolder singleton =
ShenyuPluginClassLoaderHolder.getSingleton();
if (Objects.isNull(uploadedJarResource)) {
- List<PluginJarParser.PluginJar> uploadPluginJars =
ShenyuExtPathPluginJarLoader.loadExtendPlugins(shenyuConfig.getExtPlugin().getPath());
- for (PluginJarParser.PluginJar extPath : uploadPluginJars) {
+ ExtPluginLoadResult loadResult =
ShenyuExtPathPluginJarLoader.loadExtendPlugins(shenyuConfig.getExtPlugin().getPath());
+
webHandler.removeExtPlugins(loadResult.getRemovedPluginNames());
+ for (PluginJarParser.PluginJar extPath :
loadResult.getPluginJars()) {
LOG.info("shenyu extPlugin find new {} to load",
extPath.getAbsolutePath());
ShenyuPluginClassLoader extPathClassLoader =
singleton.createPluginClassLoader(extPath);
plugins.addAll(extPathClassLoader.loadUploadedJarPlugins());
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoader.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoader.java
index fe705f36b6..bf4e74b8bc 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoader.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoader.java
@@ -56,6 +56,8 @@ public final class ShenyuPluginClassLoader extends
ClassLoader implements Closea
private final Map<String, byte[]> resourceCache = new
ConcurrentHashMap<>();
+ private final Set<String> loadedPluginNames =
ConcurrentHashMap.newKeySet();
+
private final PluginJarParser.PluginJar pluginJar;
public ShenyuPluginClassLoader(final PluginJarParser.PluginJar pluginJar) {
@@ -90,7 +92,11 @@ public final class ShenyuPluginClassLoader extends
ClassLoader implements Closea
try {
instance = getOrCreateSpringBean(className);
if (Objects.nonNull(instance)) {
- results.add(buildResult(instance));
+ ShenyuLoaderResult result = buildResult(instance);
+ results.add(result);
+ if (Objects.nonNull(result.getShenyuPlugin())) {
+
loadedPluginNames.add(result.getShenyuPlugin().named());
+ }
LOG.info("The class successfully loaded into a
upload-Jar-plugin {} is registered as a spring bean", className);
}
} catch (ClassNotFoundException | IllegalAccessException |
InstantiationException e) {
@@ -218,4 +224,13 @@ public final class ShenyuPluginClassLoader extends
ClassLoader implements Closea
return pluginJar.getVersion().equals(version);
}
+ /**
+ * Get loaded plugin names.
+ *
+ * @return loaded plugin names
+ */
+ public Set<String> getLoadedPluginNames() {
+ return Set.copyOf(loadedPluginNames);
+ }
+
}
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoaderHolder.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoaderHolder.java
index 388911914c..d5af90eafb 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoaderHolder.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/loader/ShenyuPluginClassLoaderHolder.java
@@ -17,8 +17,11 @@
package org.apache.shenyu.web.loader;
+import java.util.Collections;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -62,11 +65,16 @@ public final class ShenyuPluginClassLoaderHolder {
* removePluginClassLoader.
*
* @param jarKey jarKey
+ * @return removed plugin names
*/
- public void removePluginClassLoader(final String jarKey) {
- if (pluginCache.containsKey(jarKey)) {
- pluginCache.remove(jarKey).close();
+ public Set<String> removePluginClassLoader(final String jarKey) {
+ ShenyuPluginClassLoader classLoader = pluginCache.remove(jarKey);
+ if (Objects.nonNull(classLoader)) {
+ Set<String> pluginNames = classLoader.getLoadedPluginNames();
+ classLoader.close();
+ return pluginNames;
}
+ return Collections.emptySet();
}
}
diff --git
a/shenyu-web/src/test/java/org/apache/shenyu/web/handler/ShenyuWebHandlerTest.java
b/shenyu-web/src/test/java/org/apache/shenyu/web/handler/ShenyuWebHandlerTest.java
index 2b366f22cf..5234706fde 100644
---
a/shenyu-web/src/test/java/org/apache/shenyu/web/handler/ShenyuWebHandlerTest.java
+++
b/shenyu-web/src/test/java/org/apache/shenyu/web/handler/ShenyuWebHandlerTest.java
@@ -44,6 +44,7 @@ import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -100,6 +101,13 @@ public final class ShenyuWebHandlerTest {
assertTrue(Modifier.isSynchronized(ShenyuWebHandler.class.getMethod("putExtPlugins",
List.class).getModifiers()));
}
+ @Test
+ public void removeExtPlugins() {
+ shenyuWebHandler.removeExtPlugins(Collections.emptySet());
+ shenyuWebHandler.removeExtPlugins(Set.of(plugin1.named()));
+ assertEquals(Collections.singletonList(plugin2),
shenyuWebHandler.getPlugins());
+ }
+
@Test
public void scheduledEnableTest() {
final ServerWebExchange exchange =
MockServerWebExchange.from(MockServerHttpRequest.get("localhost")