refactor: SPI 插件目录改为 satoken

This commit is contained in:
click33
2025-02-24 19:48:33 +08:00
parent a97e3f9902
commit c04241d3b3
11 changed files with 68 additions and 8 deletions

View File

@@ -45,4 +45,14 @@ public class SaTokenPluginException extends SaTokenException {
super(cause); super(cause);
} }
/**
* 一个异常:代表插件安装过程中出现异常
*
* @param message 异常描述
* @param cause 异常对象
*/
public SaTokenPluginException(String message, Throwable cause) {
super(message, cause);
}
} }

View File

@@ -19,10 +19,14 @@ import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.exception.SaTokenPluginException; import cn.dev33.satoken.exception.SaTokenPluginException;
import cn.dev33.satoken.fun.hooks.SaTokenPluginHookFunction; import cn.dev33.satoken.fun.hooks.SaTokenPluginHookFunction;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.ServiceLoader;
/** /**
* Sa-Token 插件管理器,管理所有插件的加载与卸载 * Sa-Token 插件管理器,管理所有插件的加载与卸载
@@ -38,13 +42,18 @@ public class SaTokenPluginHolder {
public static SaTokenPluginHolder instance = new SaTokenPluginHolder(); public static SaTokenPluginHolder instance = new SaTokenPluginHolder();
// ------------------- 插件初始化相关 ------------------- // ------------------- 插件管理器初始化相关 -------------------
/** /**
* 是否已经加载过插件 * 是否已经加载过插件
*/ */
public boolean isLoader = false; public boolean isLoader = false;
/**
* SPI 文件所在目录名称
*/
public String spiDir = "satoken";
/** /**
* 初始化加载所有插件(多次调用只会执行一次) * 初始化加载所有插件(多次调用只会执行一次)
*/ */
@@ -58,16 +67,57 @@ public class SaTokenPluginHolder {
/** /**
* 根据 SPI 机制加载所有插件 * 根据 SPI 机制加载所有插件
* <p>
* 加载所有 jar 下 /META-INF/satoken/ 目录下 cn.dev33.satoken.plugin.SaTokenPlugin 文件指定的实现类
* </p>
*/ */
public synchronized void loaderPlugins() { public synchronized void loaderPlugins() {
SaManager.getLog().info("SPI 插件加载开始 ..."); SaManager.getLog().info("SPI 插件加载开始 ...");
ServiceLoader<SaTokenPlugin> plugins = ServiceLoader.load(SaTokenPlugin.class); List<SaTokenPlugin> plugins = _loaderPluginsBySpi(SaTokenPlugin.class, spiDir);
for (SaTokenPlugin plugin : plugins) { for (SaTokenPlugin plugin : plugins) {
installPlugin(plugin); installPlugin(plugin);
} }
SaManager.getLog().info("SPI 插件加载结束 ..."); SaManager.getLog().info("SPI 插件加载结束 ...");
} }
/**
* 自定义 SPI 读取策略 (无状态函数)
* @param serviceInterface SPI 接口
* @param dirName 目录名称
* @return /
* @param <T> /
*/
protected <T> List<T> _loaderPluginsBySpi(Class<T> serviceInterface, String dirName) {
String path = "META-INF/" + dirName + "/" + serviceInterface.getName();
List<T> providers = new ArrayList<>();
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> resources = classLoader.getResources(path);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
try (InputStream is = url.openStream()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
// 忽略空行和注释行
if (!line.isEmpty() && !line.startsWith("#")) {
Class<?> clazz = Class.forName(line, true, classLoader);
T instance = serviceInterface.cast(clazz.getDeclaredConstructor().newInstance());
providers.add(instance);
}
}
} catch (Exception e) {
throw new SaTokenPluginException("SPI 插件加载失败: " + e.getMessage(), e);
}
}
} catch (Exception e) {
throw new RuntimeException("SPI 插件加载失败: " + e.getMessage(), e);
}
return providers;
}
// ------------------- 插件管理 ------------------- // ------------------- 插件管理 -------------------

View File

@@ -36,10 +36,10 @@
<!-- Sa-Token 权限认证, 在线文档https://sa-token.cc/ --> <!-- Sa-Token 权限认证, 在线文档https://sa-token.cc/ -->
<dependency> <dependency>
<groupId>cn.dev33</groupId> <groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId> <artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa-token.version}</version> <version>${sa-token.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>