增强插件系统:优化插件管理和动态插件实现

- 在插件管理器中引入 DynamicPlugin 结构体,支持动态加载和管理插件,提升插件的灵活性和可扩展性。
- 更新插件接口,添加插件名称、版本、描述、作者、类型和启用状态的获取和设置方法,增强插件信息的管理能力。
- 修改现有插件实现,确保兼容新的动态插件结构,提升插件的统一性和可维护性。
- 更新示例程序,展示如何使用新的动态插件功能,提升用户体验。

此更新提升了插件系统的灵活性和可扩展性,便于开发者更好地管理和使用插件功能。
This commit is contained in:
2025-03-14 07:12:05 +00:00
parent cc4c677553
commit 557059b2d2
11 changed files with 701 additions and 107 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.idea .idea
.vscode .vscode
*.so

View File

@@ -0,0 +1 @@
{}

View File

@@ -405,6 +405,19 @@ func APIPluginsHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
plugins := pm.GetPluginInfos() plugins := pm.GetPluginInfos()
fmt.Printf("API请求: 找到 %d 个插件\n", len(plugins))
// 打印每个插件的信息
for i, p := range plugins {
fmt.Printf("插件 %d: 名称=%s, 版本=%s, 作者=%s, 类型=%s, 启用=%v\n",
i+1, p.Name, p.Version, p.Author, p.Type, p.Enabled)
}
// 如果没有插件,返回一个空数组而不是 null
if plugins == nil {
plugins = []plugin.PluginInfo{}
}
if err := json.NewEncoder(w).Encode(plugins); err != nil { if err := json.NewEncoder(w).Encode(plugins); err != nil {
http.Error(w, fmt.Sprintf("编码JSON失败: %v", err), http.StatusInternalServerError) http.Error(w, fmt.Sprintf("编码JSON失败: %v", err), http.StatusInternalServerError)
} }
@@ -427,7 +440,7 @@ func getPluginInfo(name string) (*plugin.PluginInfo, map[string]interface{}) {
// 插件目录 // 插件目录
var pluginsDir = "./plugins" var pluginsDir = "./plugins"
func main3() { func main() {
// 创建插件管理器 // 创建插件管理器
pm = plugin.NewPluginManager(pluginsDir) pm = plugin.NewPluginManager(pluginsDir)

View File

@@ -134,16 +134,6 @@ type PluginInfo struct {
Config map[string]interface{} ` + "`json:\"config,omitempty\"`" + ` Config map[string]interface{} ` + "`json:\"config,omitempty\"`" + `
} }
// PluginType 插件类型
type PluginType string
const (
PluginTypeGeneral PluginType = "General"
PluginTypeStorage PluginType = "Storage"
PluginTypeUtils PluginType = "Utils"
PluginTypeNetwork PluginType = "Network"
)
// OperationInfo 操作信息 // OperationInfo 操作信息
type OperationInfo struct { type OperationInfo struct {
Name string ` + "`json:\"name\"`" + ` Name string ` + "`json:\"name\"`" + `

View File

@@ -236,7 +236,7 @@ func (p *LogPlugin) Log(message string) {
func main() { func main() {
// 创建插件管理器 // 创建插件管理器
pluginsDir := "./plugins" pluginsDir := "../admin/plugins"
pm := plugin.NewPluginManager(pluginsDir) pm := plugin.NewPluginManager(pluginsDir)
// 检查当前系统是否支持动态加载插件 // 检查当前系统是否支持动态加载插件

View File

@@ -3,7 +3,6 @@ package plugin
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io/fs" "io/fs"
"os" "os"
@@ -978,36 +977,445 @@ func (pm *PluginManager) loadPlugin(path string) error {
return fmt.Errorf("查找Plugin变量失败: %v", err) return fmt.Errorf("查找Plugin变量失败: %v", err)
} }
// 类型断言 // 使用反射检查插件对象
plugin, ok := symPlugin.(Plugin) pluginValue := reflect.ValueOf(symPlugin)
if !ok { fmt.Printf("加载插件: %s, 类型: %s\n", path, pluginValue.Type())
return errors.New("插件类型错误")
// 查找基本字段或方法
var pluginName, pluginVersion, pluginAuthor, pluginDesc string
var pluginType PluginType = PluginTypeGeneral
var enabled = true
// 直接检查方法
// 尝试通过方法获取信息
nameFound := false
if nameMethod := pluginValue.MethodByName("Name"); nameMethod.IsValid() {
results := nameMethod.Call(nil)
if len(results) > 0 && results[0].Kind() == reflect.String {
pluginName = results[0].String()
nameFound = true
}
}
if versionMethod := pluginValue.MethodByName("Version"); versionMethod.IsValid() {
results := versionMethod.Call(nil)
if len(results) > 0 && results[0].Kind() == reflect.String {
pluginVersion = results[0].String()
}
}
if descMethod := pluginValue.MethodByName("Description"); descMethod.IsValid() {
results := descMethod.Call(nil)
if len(results) > 0 && results[0].Kind() == reflect.String {
pluginDesc = results[0].String()
}
}
if authorMethod := pluginValue.MethodByName("Author"); authorMethod.IsValid() {
results := authorMethod.Call(nil)
if len(results) > 0 && results[0].Kind() == reflect.String {
pluginAuthor = results[0].String()
}
}
if typeMethod := pluginValue.MethodByName("Type"); typeMethod.IsValid() {
results := typeMethod.Call(nil)
if len(results) > 0 {
// 尝试匹配插件类型
typeStr := fmt.Sprint(results[0].Interface())
switch typeStr {
case "storage":
pluginType = PluginTypeStorage
case "security":
pluginType = PluginTypeSecurity
case "network":
pluginType = PluginTypeNetwork
case "utils":
pluginType = PluginTypeUtils
case "hardware":
pluginType = PluginTypeHardware
case "ui":
pluginType = PluginTypeUI
}
}
}
// 直接检查字段(仅在方法不可用时)
if !nameFound && pluginValue.Kind() == reflect.Ptr && !pluginValue.IsNil() {
elemValue := pluginValue.Elem()
// 检查elemValue是否为结构体
if elemValue.Kind() == reflect.Struct {
// 检查是否有name字段
if nameField := elemValue.FieldByName("name"); nameField.IsValid() && nameField.Kind() == reflect.String {
pluginName = nameField.String()
}
// 检查是否有version字段
if versionField := elemValue.FieldByName("version"); versionField.IsValid() && versionField.Kind() == reflect.String {
pluginVersion = versionField.String()
}
// 检查是否有description字段
if descField := elemValue.FieldByName("description"); descField.IsValid() && descField.Kind() == reflect.String {
pluginDesc = descField.String()
}
// 检查是否有author字段
if authorField := elemValue.FieldByName("author"); authorField.IsValid() && authorField.Kind() == reflect.String {
pluginAuthor = authorField.String()
}
// 检查是否有pluginType字段
if typeField := elemValue.FieldByName("pluginType"); typeField.IsValid() {
// 转换为字符串并尝试匹配已知类型
typeStr := fmt.Sprint(typeField.Interface())
switch typeStr {
case "storage":
pluginType = PluginTypeStorage
case "security":
pluginType = PluginTypeSecurity
case "network":
pluginType = PluginTypeNetwork
case "utils":
pluginType = PluginTypeUtils
case "hardware":
pluginType = PluginTypeHardware
case "ui":
pluginType = PluginTypeUI
}
}
// 检查是否有enabled字段
if enabledField := elemValue.FieldByName("enabled"); enabledField.IsValid() && enabledField.Kind() == reflect.Bool {
enabled = enabledField.Bool()
}
}
}
// 如果名称仍为空,则使用文件名
if pluginName == "" {
// 从路径中提取文件名并去掉扩展名
fileName := filepath.Base(path)
pluginName = strings.TrimSuffix(fileName, filepath.Ext(fileName))
}
fmt.Printf("创建适配器插件: 名称=%s, 版本=%s, 作者=%s, 类型=%s\n",
pluginName, pluginVersion, pluginAuthor, pluginType)
// 创建一个自定义插件结构体
customPlugin := &DynamicPlugin{
original: symPlugin,
name: pluginName,
version: pluginVersion,
description: pluginDesc,
author: pluginAuthor,
pluginType: pluginType,
enabled: enabled,
} }
// 检查插件名称是否已存在 // 检查插件名称是否已存在
pm.mu.Lock() pm.mu.Lock()
defer pm.mu.Unlock() defer pm.mu.Unlock()
if _, exists := pm.plugins[plugin.Name()]; exists { if _, exists := pm.plugins[customPlugin.Name()]; exists {
return fmt.Errorf("插件 %s 已存在", plugin.Name()) return fmt.Errorf("插件 %s 已存在", customPlugin.Name())
} }
// 设置插件启用状态 // 设置插件启用状态
if config, exists := pm.configs[plugin.Name()]; exists { if config, exists := pm.configs[customPlugin.Name()]; exists {
if enabled, ok := config["enabled"].(bool); ok { if enabled, ok := config["enabled"].(bool); ok {
plugin.SetEnabled(enabled) customPlugin.enabled = enabled
} else {
plugin.SetEnabled(true) // 默认启用
} }
} else {
plugin.SetEnabled(true) // 默认启用
} }
// 注册插件 // 注册插件
pm.registerPlugin(plugin) pm.registerPlugin(customPlugin)
fmt.Printf("已成功注册插件: %s\n", customPlugin.Name())
return nil return nil
} }
// DynamicPlugin 完全动态的插件实现
type DynamicPlugin struct {
original interface{}
name string
version string
description string
author string
pluginType PluginType
enabled bool
}
// Name 返回插件名称
func (p *DynamicPlugin) Name() string {
return p.name
}
// Version 返回插件版本
func (p *DynamicPlugin) Version() string {
return p.version
}
// Description 返回插件描述
func (p *DynamicPlugin) Description() string {
return p.description
}
// Author 返回插件作者
func (p *DynamicPlugin) Author() string {
return p.author
}
// Type 返回插件类型
func (p *DynamicPlugin) Type() PluginType {
return p.pluginType
}
// IsEnabled 返回插件是否启用
func (p *DynamicPlugin) IsEnabled() bool {
return p.enabled
}
// SetEnabled 设置插件启用状态
func (p *DynamicPlugin) SetEnabled(enabled bool) {
p.enabled = enabled
// 尝试调用原始插件的SetEnabled方法
method := reflect.ValueOf(p.original).MethodByName("SetEnabled")
if method.IsValid() {
method.Call([]reflect.Value{reflect.ValueOf(enabled)})
}
}
// Init 初始化插件
func (p *DynamicPlugin) Init(ctx context.Context, config map[string]interface{}) error {
method := reflect.ValueOf(p.original).MethodByName("Init")
if !method.IsValid() {
return nil // 如果方法不存在,就不做任何事情
}
// 确定方法参数数量和类型
methodType := method.Type()
numParams := methodType.NumIn()
// 准备参数
var args []reflect.Value
// 对于不同参数数量的处理
switch numParams {
case 0:
// 无参数
case 1:
// 只有一个参数,可能是配置
args = append(args, reflect.ValueOf(config))
case 2:
// 两个参数,可能是上下文和配置
args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(config))
default:
// 不支持更多参数
return fmt.Errorf("不支持的Init方法参数数量: %d", numParams)
}
// 调用方法
results := method.Call(args)
// 处理返回值
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
if !results[0].IsNil() {
return results[0].Interface().(error)
}
}
return nil
}
// Start 启动插件
func (p *DynamicPlugin) Start(ctx context.Context) error {
method := reflect.ValueOf(p.original).MethodByName("Start")
if !method.IsValid() {
return nil // 如果方法不存在,就不做任何事情
}
// 确定方法参数数量和类型
methodType := method.Type()
numParams := methodType.NumIn()
// 准备参数
var args []reflect.Value
// 对于不同参数数量的处理
switch numParams {
case 0:
// 无参数
case 1:
// 一个参数,可能是上下文
args = append(args, reflect.ValueOf(ctx))
default:
// 不支持更多参数
return fmt.Errorf("不支持的Start方法参数数量: %d", numParams)
}
// 调用方法
results := method.Call(args)
// 处理返回值
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
if !results[0].IsNil() {
return results[0].Interface().(error)
}
}
return nil
}
// Stop 停止插件
func (p *DynamicPlugin) Stop(ctx context.Context) error {
method := reflect.ValueOf(p.original).MethodByName("Stop")
if !method.IsValid() {
return nil // 如果方法不存在,就不做任何事情
}
// 确定方法参数数量和类型
methodType := method.Type()
numParams := methodType.NumIn()
// 准备参数
var args []reflect.Value
// 对于不同参数数量的处理
switch numParams {
case 0:
// 无参数
case 1:
// 一个参数,可能是上下文
args = append(args, reflect.ValueOf(ctx))
default:
// 不支持更多参数
return fmt.Errorf("不支持的Stop方法参数数量: %d", numParams)
}
// 调用方法
results := method.Call(args)
// 处理返回值
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
if !results[0].IsNil() {
return results[0].Interface().(error)
}
}
return nil
}
// Execute 执行插件功能
func (p *DynamicPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
method := reflect.ValueOf(p.original).MethodByName("Execute")
if !method.IsValid() {
return nil, fmt.Errorf("插件不支持Execute方法")
}
// 确定方法参数数量和类型
methodType := method.Type()
numParams := methodType.NumIn()
// 准备参数
var args []reflect.Value
// 对于不同参数数量的处理
switch numParams {
case 2:
// 两个参数可能是action和params
args = append(args, reflect.ValueOf(action), reflect.ValueOf(params))
case 3:
// 三个参数可能是ctx、action和params
args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(action), reflect.ValueOf(params))
default:
// 不支持其他参数数量
return nil, fmt.Errorf("不支持的Execute方法参数数量: %d", numParams)
}
// 调用方法
results := method.Call(args)
// 处理返回值
var result interface{}
var err error
switch len(results) {
case 1:
// 只有一个返回值,检查是否为错误
if results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
if !results[0].IsNil() {
err = results[0].Interface().(error)
}
} else {
result = results[0].Interface()
}
case 2:
// 两个返回值,第一个是结果,第二个是错误
if !results[0].IsNil() {
result = results[0].Interface()
}
if results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
if !results[1].IsNil() {
err = results[1].Interface().(error)
}
}
}
return result, err
}
// GetOperationInfo 获取操作的参数信息
func (p *DynamicPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
method := reflect.ValueOf(p.original).MethodByName("GetOperationInfo")
if !method.IsValid() {
return map[string]interface{}{}, nil
}
results := method.Call([]reflect.Value{reflect.ValueOf(operation)})
var result map[string]interface{}
var err error
if len(results) > 0 && !results[0].IsNil() {
if m, ok := results[0].Interface().(map[string]interface{}); ok {
result = m
} else {
result = map[string]interface{}{}
}
} else {
result = map[string]interface{}{}
}
if len(results) > 1 && results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
if !results[1].IsNil() {
err = results[1].Interface().(error)
}
}
return result, err
}
// GetAllOperations 获取所有操作及其参数信息
func (p *DynamicPlugin) GetAllOperations() map[string]map[string]interface{} {
method := reflect.ValueOf(p.original).MethodByName("GetAllOperations")
if !method.IsValid() {
return map[string]map[string]interface{}{}
}
results := method.Call(nil)
if len(results) > 0 && !results[0].IsNil() {
if m, ok := results[0].Interface().(map[string]map[string]interface{}); ok {
return m
}
}
return map[string]map[string]interface{}{}
}
// registerPlugin 注册插件到插件管理器 // registerPlugin 注册插件到插件管理器
func (pm *PluginManager) registerPlugin(plugin Plugin) { func (pm *PluginManager) registerPlugin(plugin Plugin) {
pluginType := plugin.Type() pluginType := plugin.Type()
@@ -1460,4 +1868,4 @@ func (pm *PluginManager) GetAllPluginsOperations() map[string]map[string]map[str
} }
return result return result
} }

12
examples/plugin/plugins/build.sh Normal file → Executable file
View File

@@ -3,14 +3,14 @@
# 构建脚本,用于编译所有插件 # 构建脚本,用于编译所有插件
# 确保输出目录存在 # 确保输出目录存在
mkdir -p dist mkdir -p ../../admin/plugins
echo "===== 开始编译插件 =====" echo "===== 开始编译插件 ====="
# 编译带有明确类型的日志插件 # 编译带有明确类型的日志插件
echo "编译日志插件 (明确类型)..." echo "编译日志插件 (明确类型)..."
cd logger cd logger
go build -buildmode=plugin -o ../dist/logger.so go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/logger.so
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "日志插件编译成功!" echo "日志插件编译成功!"
else else
@@ -22,7 +22,7 @@ cd ..
# 编译使用默认类型的日志插件 # 编译使用默认类型的日志插件
echo "编译默认日志插件 (默认类型)..." echo "编译默认日志插件 (默认类型)..."
cd defaultlogger cd defaultlogger
go build -buildmode=plugin -o ../dist/defaultlogger.so go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/defaultlogger.so
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "默认日志插件编译成功!" echo "默认日志插件编译成功!"
else else
@@ -34,7 +34,7 @@ cd ..
# 编译统计插件 # 编译统计插件
echo "编译统计插件..." echo "编译统计插件..."
cd stats cd stats
go build -buildmode=plugin -o ../dist/stats.so go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/stats.so
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "统计插件编译成功!" echo "统计插件编译成功!"
else else
@@ -46,7 +46,7 @@ cd ..
# 编译存储插件 # 编译存储插件
echo "编译存储插件..." echo "编译存储插件..."
cd storage cd storage
go build -buildmode=plugin -o ../dist/storage.so go build -buildmode=plugin -ldflags "-s -w" -o ../../admin/plugins/storage.so
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "存储插件编译成功!" echo "存储插件编译成功!"
else else
@@ -56,8 +56,6 @@ fi
cd .. cd ..
echo "===== 所有插件编译完成 =====" echo "===== 所有插件编译完成 ====="
echo "插件文件保存在 dist 目录中:"
ls -la dist/
# 对于Windows系统添加.exe后缀 # 对于Windows系统添加.exe后缀
# go build -buildmode=plugin -o ../dist/plugin_name.dll # go build -buildmode=plugin -o ../dist/plugin_name.dll

View File

@@ -14,22 +14,73 @@ import (
// DefaultLoggerPlugin 默认日志插件 // DefaultLoggerPlugin 默认日志插件
// 提供文件日志和控制台日志功能,使用默认插件类型 // 提供文件日志和控制台日志功能,使用默认插件类型
type DefaultLoggerPlugin struct { type DefaultLoggerPlugin struct {
*plugin.BasePlugin // 嵌入基本插件结构 plugin.Plugin // 嵌入接口,确保类型检查
logFile *os.File // 日志文件 name string // 插件名称
logger *log.Logger // 日志记录器 version string // 插件版本
config map[string]interface{} // 配置 description string // 插件描述
author string // 插件作者
pluginType plugin.PluginType // 插件类型
enabled bool // 是否启用
logFile *os.File // 日志文件
logger *log.Logger // 日志记录器
config map[string]interface{} // 配置
} }
// Plugin 导出的插件变量 // Plugin 导出的插件变量
// 注意变量名必须是Plugin大小写敏感 // 注意变量名必须是Plugin大小写敏感
// 这个插件使用默认的通用插件类型PluginTypeGeneral // 这个插件使用默认的通用插件类型PluginTypeGeneral
var Plugin = &DefaultLoggerPlugin{ var Plugin = &DefaultLoggerPlugin{
BasePlugin: plugin.NewBasePluginWithDefaultType( name: "DefaultLoggerPlugin",
"DefaultLoggerPlugin", version: "1.0.0",
"1.0.0", description: "使用默认通用类型的日志记录插件",
"使用默认通用类型的日志记录插件", author: "开发者",
"开发者", pluginType: plugin.PluginTypeGeneral, // 使用通用插件类型
), // 将自动使用 PluginTypeGeneral 类型 enabled: true,
}
// Name 返回插件名称
func (p *DefaultLoggerPlugin) Name() string {
return p.name
}
// Version 返回插件版本
func (p *DefaultLoggerPlugin) Version() string {
return p.version
}
// Description 返回插件描述
func (p *DefaultLoggerPlugin) Description() string {
return p.description
}
// Author 返回插件作者
func (p *DefaultLoggerPlugin) Author() string {
return p.author
}
// Type 返回插件类型
func (p *DefaultLoggerPlugin) Type() plugin.PluginType {
return p.pluginType
}
// IsEnabled 返回插件是否启用
func (p *DefaultLoggerPlugin) IsEnabled() bool {
return p.enabled
}
// SetEnabled 设置插件启用状态
func (p *DefaultLoggerPlugin) SetEnabled(enabled bool) {
p.enabled = enabled
}
// GetOperationInfo 获取操作的参数信息
func (p *DefaultLoggerPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
return map[string]interface{}{}, nil
}
// GetAllOperations 获取所有操作及其参数信息
func (p *DefaultLoggerPlugin) GetAllOperations() map[string]map[string]interface{} {
return map[string]map[string]interface{}{}
} }
// Init 初始化插件 // Init 初始化插件

View File

@@ -14,36 +14,73 @@ import (
// LoggerPlugin 日志插件 // LoggerPlugin 日志插件
// 提供文件日志和控制台日志功能 // 提供文件日志和控制台日志功能
type LoggerPlugin struct { type LoggerPlugin struct {
*plugin.BasePlugin // 嵌入基本插件结构 plugin.Plugin // 嵌入接口,确保类型检查
logFile *os.File // 日志文件 name string // 插件名称
logger *log.Logger // 日志记录器 version string // 插件版本
config map[string]interface{} // 配置 description string // 插件描述
author string // 插件作者
pluginType plugin.PluginType // 插件类型
enabled bool // 是否启用
logFile *os.File // 日志文件
logger *log.Logger // 日志记录器
config map[string]interface{} // 配置
} }
// Plugin 导出的插件变量 // Plugin 导出的插件变量
// 注意变量名必须是Plugin大小写敏感 // 注意变量名必须是Plugin大小写敏感
// 使用方式1: 明确指定插件类型
var Plugin = &LoggerPlugin{ var Plugin = &LoggerPlugin{
BasePlugin: plugin.NewBasePlugin( name: "LoggerPlugin",
"LoggerPlugin", version: "1.0.0",
"1.0.0", description: "简单的日志记录插件",
"简单的日志记录插件", author: "开发者",
"开发者", pluginType: plugin.PluginTypeUtils, // 明确指定为工具类插件
plugin.PluginTypeUtils, // 明确指定为工具类插件 enabled: true,
),
} }
// 使用方式2: 使用默认插件类型(通用插件) // Name 返回插件名称
// 如果您不关心插件类型或想使用默认的通用插件类型,可以使用以下方式: func (p *LoggerPlugin) Name() string {
// return p.name
// var Plugin = &LoggerPlugin{ }
// BasePlugin: plugin.NewBasePluginWithDefaultType(
// "LoggerPlugin", // Version 返回插件版本
// "1.0.0", func (p *LoggerPlugin) Version() string {
// "简单的日志记录插件", return p.version
// "开发者", }
// ), // 将自动使用 PluginTypeGeneral 类型
// } // Description 返回插件描述
func (p *LoggerPlugin) Description() string {
return p.description
}
// Author 返回插件作者
func (p *LoggerPlugin) Author() string {
return p.author
}
// Type 返回插件类型
func (p *LoggerPlugin) Type() plugin.PluginType {
return p.pluginType
}
// IsEnabled 返回插件是否启用
func (p *LoggerPlugin) IsEnabled() bool {
return p.enabled
}
// SetEnabled 设置插件启用状态
func (p *LoggerPlugin) SetEnabled(enabled bool) {
p.enabled = enabled
}
// GetOperationInfo 获取操作的参数信息
func (p *LoggerPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
return map[string]interface{}{}, nil
}
// GetAllOperations 获取所有操作及其参数信息
func (p *LoggerPlugin) GetAllOperations() map[string]map[string]interface{} {
return map[string]map[string]interface{}{}
}
// Init 初始化插件 // Init 初始化插件
func (p *LoggerPlugin) Init(ctx context.Context, config map[string]interface{}) error { func (p *LoggerPlugin) Init(ctx context.Context, config map[string]interface{}) error {

View File

@@ -12,13 +12,19 @@ import (
// StatsPlugin 统计插件 // StatsPlugin 统计插件
// 用于收集和记录系统运行时统计数据 // 用于收集和记录系统运行时统计数据
type StatsPlugin struct { type StatsPlugin struct {
*plugin.BasePluginImpl // 改为使用BasePluginImpl plugin.Plugin // 嵌入接口,确保类型检查
stats map[string]int64 name string // 插件名称
startTime time.Time version string // 插件版本
mu sync.RWMutex description string // 插件描述
tickerStop chan bool author string // 插件作者
ticker *time.Ticker pluginType plugin.PluginType // 插件类型
config map[string]interface{} enabled bool // 是否启用
stats map[string]int64
startTime time.Time
mu sync.RWMutex
tickerStop chan bool
ticker *time.Ticker
config map[string]interface{}
} }
// StatsParams 统计请求参数结构体 // StatsParams 统计请求参数结构体
@@ -33,29 +39,60 @@ type StatsParams struct {
// Plugin 导出的插件变量 // Plugin 导出的插件变量
var Plugin = &StatsPlugin{ var Plugin = &StatsPlugin{
// 使用默认构造函数,不指定插件类型,将默认为通用插件 name: "StatsPlugin",
BasePluginImpl: plugin.NewPluginWithDefaultType( version: "1.0.0",
"StatsPlugin", description: "系统运行时统计插件",
"1.0.0", author: "开发者",
"系统运行时统计插件", pluginType: plugin.PluginTypeUtils, // 指定为工具类插件
"开发者", enabled: true,
), stats: make(map[string]int64),
stats: make(map[string]int64), tickerStop: make(chan bool),
tickerStop: make(chan bool),
} }
// 为展示如何指定类型,我们也可以显式设置插件类型 // Name 返回插件名称
// var Plugin = &StatsPlugin{ func (p *StatsPlugin) Name() string {
// BasePlugin: plugin.NewBasePlugin( return p.name
// "StatsPlugin", }
// "1.0.0",
// "系统运行时统计插件", // Version 返回插件版本
// "开发者", func (p *StatsPlugin) Version() string {
// plugin.PluginTypeUtils, // 明确指定为工具类插件 return p.version
// ), }
// stats: make(map[string]int64),
// tickerStop: make(chan bool), // Description 返回插件描述
// } func (p *StatsPlugin) Description() string {
return p.description
}
// Author 返回插件作者
func (p *StatsPlugin) Author() string {
return p.author
}
// Type 返回插件类型
func (p *StatsPlugin) Type() plugin.PluginType {
return p.pluginType
}
// IsEnabled 返回插件是否启用
func (p *StatsPlugin) IsEnabled() bool {
return p.enabled
}
// SetEnabled 设置插件启用状态
func (p *StatsPlugin) SetEnabled(enabled bool) {
p.enabled = enabled
}
// GetOperationInfo 获取操作的参数信息
func (p *StatsPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
return map[string]interface{}{}, nil
}
// GetAllOperations 获取所有操作及其参数信息
func (p *StatsPlugin) GetAllOperations() map[string]map[string]interface{} {
return map[string]map[string]interface{}{}
}
// Init 初始化插件 // Init 初始化插件
func (p *StatsPlugin) Init(ctx context.Context, config map[string]interface{}) error { func (p *StatsPlugin) Init(ctx context.Context, config map[string]interface{}) error {
@@ -242,7 +279,15 @@ func (p *StatsPlugin) logStats() {
// GetAvailableOperations 获取可用操作列表 // GetAvailableOperations 获取可用操作列表
// 这是一个帮助方法列出所有可通过Execute调用的操作 // 这是一个帮助方法列出所有可通过Execute调用的操作
func (p *StatsPlugin) GetAvailableOperations() []string { func (p *StatsPlugin) GetAvailableOperations() []string {
return p.GetAvailableActions() // 返回硬编码的操作列表,而不是调用不存在的方法
return []string{
"incrementstat",
"getstat",
"recordrequest",
"resetstats",
"generatestatsreport",
"getallstats",
}
} }
// main 函数是必须的,但不会被调用 // main 函数是必须的,但不会被调用

View File

@@ -14,22 +14,72 @@ import (
// StoragePlugin 存储插件 // StoragePlugin 存储插件
// 提供简单的文件存储功能 // 提供简单的文件存储功能
type StoragePlugin struct { type StoragePlugin struct {
*plugin.BasePlugin // 嵌入基本插件结构 plugin.Plugin // 嵌入接口,确保类型检查
storageDir string // 存储目录 name string // 插件名称
config map[string]interface{} // 配置 version string // 插件版本
mu sync.RWMutex // 读写锁 description string // 插件描述
author string // 插件作者
pluginType plugin.PluginType // 插件类型
enabled bool // 是否启用
storageDir string // 存储目录
config map[string]interface{} // 配置
mu sync.RWMutex // 读写锁
} }
// Plugin 导出的插件变量 // Plugin 导出的插件变量
// 注意变量名必须是Plugin大小写敏感 // 注意变量名必须是Plugin大小写敏感
var Plugin = &StoragePlugin{ var Plugin = &StoragePlugin{
BasePlugin: plugin.NewBasePlugin( name: "StoragePlugin",
"StoragePlugin", version: "1.0.0",
"1.0.0", description: "简单的文件存储插件",
"简单的文件存储插件", author: "开发者",
"开发者", pluginType: plugin.PluginTypeStorage, // 设置插件类型为存储插件
plugin.PluginTypeStorage, // 设置插件类型为存储插件 enabled: true,
), }
// Name 返回插件名称
func (p *StoragePlugin) Name() string {
return p.name
}
// Version 返回插件版本
func (p *StoragePlugin) Version() string {
return p.version
}
// Description 返回插件描述
func (p *StoragePlugin) Description() string {
return p.description
}
// Author 返回插件作者
func (p *StoragePlugin) Author() string {
return p.author
}
// Type 返回插件类型
func (p *StoragePlugin) Type() plugin.PluginType {
return p.pluginType
}
// IsEnabled 返回插件是否启用
func (p *StoragePlugin) IsEnabled() bool {
return p.enabled
}
// SetEnabled 设置插件启用状态
func (p *StoragePlugin) SetEnabled(enabled bool) {
p.enabled = enabled
}
// GetOperationInfo 获取操作的参数信息
func (p *StoragePlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
return map[string]interface{}{}, nil
}
// GetAllOperations 获取所有操作及其参数信息
func (p *StoragePlugin) GetAllOperations() map[string]map[string]interface{} {
return map[string]map[string]interface{}{}
} }
// Init 初始化插件 // Init 初始化插件