- 在插件管理器中引入 DynamicPlugin 结构体,支持动态加载和管理插件,提升插件的灵活性和可扩展性。 - 更新插件接口,添加插件名称、版本、描述、作者、类型和启用状态的获取和设置方法,增强插件信息的管理能力。 - 修改现有插件实现,确保兼容新的动态插件结构,提升插件的统一性和可维护性。 - 更新示例程序,展示如何使用新的动态插件功能,提升用户体验。 此更新提升了插件系统的灵活性和可扩展性,便于开发者更好地管理和使用插件功能。
367 lines
9.8 KiB
Go
367 lines
9.8 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"runtime"
|
||
"strings"
|
||
|
||
"github.com/darkit/goproxy/examples/plugin"
|
||
)
|
||
|
||
// 这是内置插件的示例实现
|
||
// LogPlugin 日志插件
|
||
type LogPlugin struct {
|
||
name string
|
||
version string
|
||
description string
|
||
author string
|
||
pluginType plugin.PluginType
|
||
enabled bool
|
||
level string
|
||
}
|
||
|
||
// 创建内置日志插件 - 示例1:明确指定插件类型
|
||
func NewLogPlugin() *LogPlugin {
|
||
return &LogPlugin{
|
||
name: "InternalLogPlugin",
|
||
version: "1.0.0",
|
||
description: "内置日志插件,在不支持动态加载插件的平台上使用",
|
||
author: "开发者",
|
||
pluginType: plugin.PluginTypeUtils, // 明确指定为工具类插件
|
||
enabled: true,
|
||
level: "info",
|
||
}
|
||
}
|
||
|
||
// 创建内置日志插件 - 示例2:使用默认插件类型(通用插件)
|
||
func NewDefaultLogPlugin() *LogPlugin {
|
||
return &LogPlugin{
|
||
name: "DefaultLogPlugin",
|
||
version: "1.0.0",
|
||
description: "使用默认类型的内置日志插件示例",
|
||
author: "开发者",
|
||
pluginType: plugin.PluginTypeGeneral, // 自动设置为通用插件类型
|
||
enabled: true,
|
||
level: "info",
|
||
}
|
||
}
|
||
|
||
// 实现Plugin接口
|
||
func (p *LogPlugin) Name() string {
|
||
return p.name
|
||
}
|
||
|
||
func (p *LogPlugin) Version() string {
|
||
return p.version
|
||
}
|
||
|
||
func (p *LogPlugin) Description() string {
|
||
return p.description
|
||
}
|
||
|
||
func (p *LogPlugin) Author() string {
|
||
return p.author
|
||
}
|
||
|
||
// Type 实现插件类型方法
|
||
func (p *LogPlugin) Type() plugin.PluginType {
|
||
return p.pluginType
|
||
}
|
||
|
||
func (p *LogPlugin) IsEnabled() bool {
|
||
return p.enabled
|
||
}
|
||
|
||
func (p *LogPlugin) SetEnabled(enabled bool) {
|
||
p.enabled = enabled
|
||
}
|
||
|
||
// GetOperationInfo 获取操作的参数信息
|
||
func (p *LogPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
|
||
// 转换为小写以便不区分大小写匹配
|
||
operation = strings.ToLower(operation)
|
||
|
||
switch operation {
|
||
case "log":
|
||
return map[string]interface{}{
|
||
"name": "log",
|
||
"description": "记录日志消息",
|
||
"parameters": map[string]interface{}{
|
||
"message": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "要记录的日志消息",
|
||
"required": true,
|
||
},
|
||
},
|
||
"returns": map[string]interface{}{
|
||
"result": map[string]interface{}{
|
||
"type": "boolean",
|
||
"description": "操作是否成功",
|
||
},
|
||
},
|
||
}, nil
|
||
case "setlevel":
|
||
return map[string]interface{}{
|
||
"name": "setLevel",
|
||
"description": "设置日志级别",
|
||
"parameters": map[string]interface{}{
|
||
"level": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "日志级别,如:info、debug、warn、error",
|
||
"required": true,
|
||
},
|
||
},
|
||
"returns": map[string]interface{}{
|
||
"result": map[string]interface{}{
|
||
"type": "boolean",
|
||
"description": "操作是否成功",
|
||
},
|
||
},
|
||
}, nil
|
||
case "getlevel":
|
||
return map[string]interface{}{
|
||
"name": "getLevel",
|
||
"description": "获取当前日志级别",
|
||
"parameters": map[string]interface{}{},
|
||
"returns": map[string]interface{}{
|
||
"result": map[string]interface{}{
|
||
"type": "string",
|
||
"description": "当前日志级别",
|
||
},
|
||
},
|
||
}, nil
|
||
case "getstatus":
|
||
return map[string]interface{}{
|
||
"name": "getStatus",
|
||
"description": "获取插件状态信息",
|
||
"parameters": map[string]interface{}{},
|
||
"returns": map[string]interface{}{
|
||
"result": map[string]interface{}{
|
||
"type": "object",
|
||
"description": "包含插件状态的对象",
|
||
"properties": map[string]interface{}{
|
||
"name": map[string]interface{}{"type": "string"},
|
||
"version": map[string]interface{}{"type": "string"},
|
||
"level": map[string]interface{}{"type": "string"},
|
||
"enabled": map[string]interface{}{"type": "boolean"},
|
||
"type": map[string]interface{}{"type": "string"},
|
||
},
|
||
},
|
||
},
|
||
}, nil
|
||
default:
|
||
return nil, fmt.Errorf("未知的操作: %s", operation)
|
||
}
|
||
}
|
||
|
||
// GetAllOperations 获取所有操作及其参数信息
|
||
func (p *LogPlugin) GetAllOperations() map[string]map[string]interface{} {
|
||
operations := make(map[string]map[string]interface{})
|
||
|
||
// 获取所有操作的信息
|
||
for _, op := range []string{"log", "setlevel", "getlevel", "getstatus"} {
|
||
info, err := p.GetOperationInfo(op)
|
||
if err == nil {
|
||
operations[op] = info
|
||
}
|
||
}
|
||
|
||
return operations
|
||
}
|
||
|
||
func (p *LogPlugin) Init(ctx context.Context, config map[string]interface{}) error {
|
||
if level, ok := config["level"].(string); ok {
|
||
p.level = level
|
||
}
|
||
fmt.Printf("内置日志插件[%s]已初始化,日志级别: %s, 插件类型: %s\n", p.name, p.level, p.Type())
|
||
return nil
|
||
}
|
||
|
||
func (p *LogPlugin) Start(ctx context.Context) error {
|
||
fmt.Printf("内置日志插件[%s]已启动\n", p.name)
|
||
return nil
|
||
}
|
||
|
||
func (p *LogPlugin) Stop(ctx context.Context) error {
|
||
fmt.Printf("内置日志插件[%s]已停止\n", p.name)
|
||
return nil
|
||
}
|
||
|
||
// Execute 实现Execute方法以满足Plugin接口
|
||
func (p *LogPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||
switch action {
|
||
case "log":
|
||
// 需要参数: message
|
||
message, ok := params["message"].(string)
|
||
if !ok {
|
||
return nil, fmt.Errorf("缺少必需参数: message")
|
||
}
|
||
p.Log(message)
|
||
return true, nil
|
||
|
||
case "setLevel":
|
||
// 需要参数: level
|
||
level, ok := params["level"].(string)
|
||
if !ok {
|
||
return nil, fmt.Errorf("缺少必需参数: level")
|
||
}
|
||
p.level = level
|
||
return true, nil
|
||
|
||
case "getLevel":
|
||
// 不需要参数,返回当前日志级别
|
||
return p.level, nil
|
||
|
||
case "getStatus":
|
||
// 返回插件状态信息
|
||
status := map[string]interface{}{
|
||
"name": p.name,
|
||
"version": p.version,
|
||
"level": p.level,
|
||
"enabled": p.enabled,
|
||
"type": p.Type(),
|
||
}
|
||
return status, nil
|
||
|
||
default:
|
||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||
}
|
||
}
|
||
|
||
// Log 记录日志
|
||
func (p *LogPlugin) Log(message string) {
|
||
fmt.Printf("[%s][%s] %s\n", p.name, p.level, message)
|
||
}
|
||
|
||
func main() {
|
||
// 创建插件管理器
|
||
pluginsDir := "../admin/plugins"
|
||
pm := plugin.NewPluginManager(pluginsDir)
|
||
|
||
// 检查当前系统是否支持动态加载插件
|
||
if pm.IsDynamicLoadingSupported() {
|
||
fmt.Printf("当前系统(%s)支持动态加载插件\n", runtime.GOOS)
|
||
} else {
|
||
fmt.Printf("当前系统(%s)不支持动态加载插件\n", runtime.GOOS)
|
||
|
||
// 在不支持动态加载的系统上注册内置插件
|
||
// 示例1:注册明确指定类型的插件
|
||
logPlugin := NewLogPlugin()
|
||
pm.RegisterPlugin(logPlugin)
|
||
|
||
// 示例2:注册使用默认类型的插件
|
||
defaultLogPlugin := NewDefaultLogPlugin()
|
||
pm.RegisterPlugin(defaultLogPlugin)
|
||
|
||
fmt.Println("已注册两个内置插件以展示不同的插件类型设置方式")
|
||
}
|
||
|
||
// 加载插件
|
||
fmt.Println("正在加载插件...")
|
||
if err := pm.LoadPlugins(); err != nil {
|
||
fmt.Printf("加载插件失败: %v\n", err)
|
||
}
|
||
|
||
// 配置插件
|
||
logPluginConfig := map[string]interface{}{
|
||
"level": "debug",
|
||
}
|
||
if err := pm.SetPluginConfig("InternalLogPlugin", logPluginConfig); err != nil {
|
||
fmt.Printf("配置插件失败: %v\n", err)
|
||
}
|
||
|
||
// 初始化插件
|
||
ctx := context.Background()
|
||
fmt.Println("正在初始化插件...")
|
||
if err := pm.InitPlugins(ctx); err != nil {
|
||
fmt.Printf("初始化插件失败: %v\n", err)
|
||
}
|
||
|
||
// 启动插件
|
||
fmt.Println("正在启动插件...")
|
||
if err := pm.StartPlugins(ctx); err != nil {
|
||
fmt.Printf("启动插件失败: %v\n", err)
|
||
}
|
||
|
||
// 获取并打印所有插件信息
|
||
fmt.Println("\n已加载的插件列表:")
|
||
plugins := pm.GetPluginInfos()
|
||
for i, info := range plugins {
|
||
status := "启用"
|
||
if !info.Enabled {
|
||
status = "禁用"
|
||
}
|
||
fmt.Printf("[%d] %s (v%s) - %s [%s]\n作者: %s\n类型: %s\n",
|
||
i, info.Name, info.Version, info.Description, status, info.Author, info.Type)
|
||
|
||
// 打印插件配置
|
||
if len(info.Config) > 0 {
|
||
fmt.Println("配置:")
|
||
for k, v := range info.Config {
|
||
fmt.Printf(" %s: %v\n", k, v)
|
||
}
|
||
}
|
||
fmt.Println()
|
||
}
|
||
|
||
// 使用第一个启用的插件(这里只是示例)
|
||
if len(plugins) > 0 {
|
||
for _, info := range plugins {
|
||
if info.Enabled {
|
||
fmt.Printf("正在使用插件: %s (类型: %s)\n", info.Name, info.Type)
|
||
if p, ok := pm.GetPlugin(info.Name); ok {
|
||
// 这里可以根据插件类型执行特定操作
|
||
if logPlugin, ok := p.(*LogPlugin); ok {
|
||
logPlugin.Log("这是一条测试日志消息")
|
||
// 改用Execute方法调用
|
||
logPlugin.Execute(ctx, "log", map[string]interface{}{
|
||
"message": "这是一条测试日志消息",
|
||
})
|
||
}
|
||
}
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
// 按类型获取和使用插件
|
||
fmt.Println("\n按类型获取插件:")
|
||
|
||
// 获取工具类插件
|
||
utilsPlugins := pm.GetPluginsByType(plugin.PluginTypeUtils)
|
||
fmt.Printf("找到 %d 个工具类插件\n", len(utilsPlugins))
|
||
for _, p := range utilsPlugins {
|
||
fmt.Printf("工具类插件: %s\n", p.Name())
|
||
if logPlugin, ok := p.(*LogPlugin); ok {
|
||
logPlugin.Log("通过类型获取到的日志插件记录消息")
|
||
// 改用Execute方法调用
|
||
logPlugin.Execute(ctx, "log", map[string]interface{}{
|
||
"message": "通过类型获取到的日志插件记录消息",
|
||
})
|
||
}
|
||
}
|
||
|
||
// 获取通用类型插件
|
||
generalPlugins := pm.GetPluginsByType(plugin.PluginTypeGeneral)
|
||
fmt.Printf("找到 %d 个通用类型插件\n", len(generalPlugins))
|
||
for _, p := range generalPlugins {
|
||
fmt.Printf("通用类型插件: %s\n", p.Name())
|
||
if logPlugin, ok := p.(*LogPlugin); ok {
|
||
logPlugin.Log("通过类型获取到的通用类型插件记录消息")
|
||
// 改用Execute方法调用
|
||
logPlugin.Execute(ctx, "log", map[string]interface{}{
|
||
"message": "通过类型获取到的通用类型插件记录消息",
|
||
})
|
||
}
|
||
}
|
||
|
||
// 停止插件
|
||
fmt.Println("\n正在停止插件...")
|
||
if err := pm.StopPlugins(ctx); err != nil {
|
||
fmt.Printf("停止插件失败: %v\n", err)
|
||
}
|
||
|
||
fmt.Println("示例结束")
|
||
}
|