增强插件系统:添加插件类型支持
- 在插件接口和基本插件结构中引入插件类型(PluginType),并定义了多种预定义的插件类型。 - 更新插件管理器以支持按类型管理插件,新增按类型获取、初始化和启动插件的方法。 - 修改现有插件(如日志插件和统计插件)以实现插件类型接口,确保兼容性。 - 优化插件信息输出,包含插件类型信息。 此更新提升了插件系统的灵活性和可扩展性,便于未来添加更多插件类型。
This commit is contained in:
132
examples/plugin/example/main.go
Normal file
132
examples/plugin/example/main.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/darkit/goproxy/examples/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建上下文
|
||||
ctx := context.Background()
|
||||
|
||||
// 获取插件目录
|
||||
pluginsDir := filepath.Join("..", "plugins")
|
||||
if _, err := os.Stat(pluginsDir); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(pluginsDir, 0o755); err != nil {
|
||||
fmt.Printf("创建插件目录失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// 创建插件管理器
|
||||
pm := plugin.NewPluginManager(pluginsDir)
|
||||
|
||||
// 检查是否支持动态加载插件
|
||||
if pm.IsDynamicLoadingSupported() {
|
||||
fmt.Println("当前系统支持动态加载插件")
|
||||
} else {
|
||||
fmt.Println("当前系统不支持动态加载插件,将使用静态插件")
|
||||
|
||||
// 在不支持动态加载的平台上注册内置插件
|
||||
// 这里需要导入并注册所有内置插件
|
||||
// 例如:pm.RegisterPlugin(logger.Plugin)
|
||||
}
|
||||
|
||||
// 加载插件
|
||||
if err := pm.LoadPlugins(); err != nil {
|
||||
fmt.Printf("加载插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 初始化所有插件
|
||||
if err := pm.InitPlugins(ctx); err != nil {
|
||||
fmt.Printf("初始化插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 启动所有插件
|
||||
if err := pm.StartPlugins(ctx); err != nil {
|
||||
fmt.Printf("启动插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 打印所有插件信息
|
||||
fmt.Println("\n=== 所有已加载的插件 ===")
|
||||
for _, info := range pm.GetPluginInfos() {
|
||||
fmt.Printf("插件名称: %s\n", info.Name)
|
||||
fmt.Printf("版本: %s\n", info.Version)
|
||||
fmt.Printf("描述: %s\n", info.Description)
|
||||
fmt.Printf("作者: %s\n", info.Author)
|
||||
fmt.Printf("类型: %s\n", info.Type)
|
||||
fmt.Printf("启用状态: %v\n", info.Enabled)
|
||||
fmt.Println("---")
|
||||
}
|
||||
|
||||
// 按类型获取插件
|
||||
fmt.Println("\n=== 按类型获取插件 ===")
|
||||
|
||||
// 获取所有存储类型插件
|
||||
storagePlugins := pm.GetPluginsByType(plugin.PluginTypeStorage)
|
||||
fmt.Printf("存储插件数量: %d\n", len(storagePlugins))
|
||||
for _, p := range storagePlugins {
|
||||
fmt.Printf("存储插件: %s (版本: %s)\n", p.Name(), p.Version())
|
||||
}
|
||||
|
||||
// 获取所有工具类型插件
|
||||
utilsPlugins := pm.GetPluginsByType(plugin.PluginTypeUtils)
|
||||
fmt.Printf("工具插件数量: %d\n", len(utilsPlugins))
|
||||
for _, p := range utilsPlugins {
|
||||
fmt.Printf("工具插件: %s (版本: %s)\n", p.Name(), p.Version())
|
||||
}
|
||||
|
||||
// 在生命周期的不同阶段按类型初始化和启动插件
|
||||
fmt.Println("\n=== 按类型初始化和启动插件 ===")
|
||||
|
||||
// 例如,在应用程序启动阶段只初始化工具插件
|
||||
if err := pm.InitPluginsByType(ctx, plugin.PluginTypeUtils); err != nil {
|
||||
fmt.Printf("初始化工具插件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("工具插件初始化成功")
|
||||
}
|
||||
|
||||
// 在需要存储功能时初始化存储插件
|
||||
if err := pm.InitPluginsByType(ctx, plugin.PluginTypeStorage); err != nil {
|
||||
fmt.Printf("初始化存储插件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("存储插件初始化成功")
|
||||
}
|
||||
|
||||
// 使用特定类型的插件示例
|
||||
fmt.Println("\n=== 使用特定类型的插件示例 ===")
|
||||
fmt.Println("注意:这部分代码在真实环境中需要使用类型断言或接口来处理")
|
||||
fmt.Println("在实际应用中,应该为每种类型的插件定义专门的接口")
|
||||
|
||||
// 按类型停止插件
|
||||
fmt.Println("\n=== 按类型停止插件 ===")
|
||||
|
||||
// 首先停止存储插件
|
||||
if err := pm.StopPluginsByType(ctx, plugin.PluginTypeStorage); err != nil {
|
||||
fmt.Printf("停止存储插件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("存储插件已停止")
|
||||
}
|
||||
|
||||
// 然后停止工具插件
|
||||
if err := pm.StopPluginsByType(ctx, plugin.PluginTypeUtils); err != nil {
|
||||
fmt.Printf("停止工具插件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("工具插件已停止")
|
||||
}
|
||||
|
||||
// 确保所有剩余插件都被停止
|
||||
if err := pm.StopPlugins(ctx); err != nil {
|
||||
fmt.Printf("停止剩余插件失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("\n所有插件已停止")
|
||||
}
|
@@ -1,5 +1,19 @@
|
||||
package plugin
|
||||
|
||||
// PluginType 插件类型
|
||||
type PluginType string
|
||||
|
||||
// 预定义的插件类型
|
||||
const (
|
||||
PluginTypeGeneral PluginType = "general" // 通用插件
|
||||
PluginTypeStorage PluginType = "storage" // 存储插件
|
||||
PluginTypeSecurity PluginType = "security" // 安全插件
|
||||
PluginTypeUI PluginType = "ui" // 用户界面插件
|
||||
PluginTypeNetwork PluginType = "network" // 网络插件
|
||||
PluginTypeUtils PluginType = "utils" // 工具插件
|
||||
// 可以根据需求添加更多插件类型
|
||||
)
|
||||
|
||||
// IPlugin 插件接口
|
||||
// 这个文件定义了所有插件必须实现的接口
|
||||
// 注意:这个文件应该与实际插件代码一起编译
|
||||
@@ -12,6 +26,8 @@ type IPlugin interface {
|
||||
Description() string
|
||||
// Author 插件作者
|
||||
Author() string
|
||||
// Type 插件类型
|
||||
Type() PluginType
|
||||
// Init 初始化插件
|
||||
Init(config map[string]interface{}) error
|
||||
// Start 启动插件
|
||||
@@ -31,16 +47,18 @@ type BasePlugin struct {
|
||||
version string
|
||||
description string
|
||||
author string
|
||||
pluginType PluginType
|
||||
enabled bool
|
||||
}
|
||||
|
||||
// NewBasePlugin 创建一个基本插件
|
||||
func NewBasePlugin(name, version, description, author string) *BasePlugin {
|
||||
func NewBasePlugin(name, version, description, author string, pluginType PluginType) *BasePlugin {
|
||||
return &BasePlugin{
|
||||
name: name,
|
||||
version: version,
|
||||
description: description,
|
||||
author: author,
|
||||
pluginType: pluginType,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
@@ -65,6 +83,11 @@ func (p *BasePlugin) Author() string {
|
||||
return p.author
|
||||
}
|
||||
|
||||
// Type 获取插件类型
|
||||
func (p *BasePlugin) Type() PluginType {
|
||||
return p.pluginType
|
||||
}
|
||||
|
||||
// IsEnabled 插件是否启用
|
||||
func (p *BasePlugin) IsEnabled() bool {
|
||||
return p.enabled
|
||||
|
@@ -17,6 +17,7 @@ type LogPlugin struct {
|
||||
author string
|
||||
enabled bool
|
||||
level string
|
||||
pluginType plugin.PluginType
|
||||
}
|
||||
|
||||
// 创建内置日志插件
|
||||
@@ -26,6 +27,7 @@ func NewLogPlugin() *LogPlugin {
|
||||
version: "1.0.0",
|
||||
description: "内置日志插件,在不支持动态加载插件的平台上使用",
|
||||
author: "开发者",
|
||||
pluginType: plugin.PluginTypeUtils, // 设置为工具类插件
|
||||
enabled: true,
|
||||
level: "info",
|
||||
}
|
||||
@@ -48,6 +50,11 @@ 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
|
||||
}
|
||||
@@ -130,8 +137,8 @@ func main() {
|
||||
if !info.Enabled {
|
||||
status = "禁用"
|
||||
}
|
||||
fmt.Printf("[%d] %s (v%s) - %s [%s]\n作者: %s\n",
|
||||
i, info.Name, info.Version, info.Description, status, info.Author)
|
||||
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 {
|
||||
@@ -159,6 +166,17 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// 按类型获取和使用插件
|
||||
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("通过类型获取到的日志插件记录消息")
|
||||
}
|
||||
}
|
||||
|
||||
// 停止插件
|
||||
fmt.Println("\n正在停止插件...")
|
||||
if err := pm.StopPlugins(ctx); err != nil {
|
||||
|
@@ -23,6 +23,8 @@ type Plugin interface {
|
||||
Description() string
|
||||
// Author 插件作者
|
||||
Author() string
|
||||
// Type 插件类型
|
||||
Type() PluginType
|
||||
// Init 初始化插件
|
||||
Init(ctx context.Context, config map[string]interface{}) error
|
||||
// Start 启动插件
|
||||
@@ -41,6 +43,7 @@ type PluginInfo struct {
|
||||
Version string `json:"version"`
|
||||
Description string `json:"description"`
|
||||
Author string `json:"author"`
|
||||
Type PluginType `json:"type"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Config map[string]interface{} `json:"config,omitempty"`
|
||||
}
|
||||
@@ -49,6 +52,7 @@ type PluginInfo struct {
|
||||
type PluginManager struct {
|
||||
pluginsDir string
|
||||
plugins map[string]Plugin
|
||||
pluginsByType map[PluginType]map[string]Plugin
|
||||
configs map[string]map[string]interface{}
|
||||
mu sync.RWMutex
|
||||
dynamicLoadingSupported bool // 是否支持动态加载插件
|
||||
@@ -62,6 +66,7 @@ func NewPluginManager(pluginsDir string) *PluginManager {
|
||||
return &PluginManager{
|
||||
pluginsDir: pluginsDir,
|
||||
plugins: make(map[string]Plugin),
|
||||
pluginsByType: make(map[PluginType]map[string]Plugin),
|
||||
configs: make(map[string]map[string]interface{}),
|
||||
dynamicLoadingSupported: dynamicLoadingSupported,
|
||||
}
|
||||
@@ -156,6 +161,7 @@ func (pm *PluginManager) savePluginConfigs() error {
|
||||
config = make(map[string]interface{})
|
||||
}
|
||||
config["enabled"] = plugin.IsEnabled()
|
||||
config["type"] = string(plugin.Type()) // 保存插件类型
|
||||
configs[name] = config
|
||||
}
|
||||
pm.mu.RUnlock()
|
||||
@@ -213,10 +219,25 @@ func (pm *PluginManager) loadPlugin(path string) error {
|
||||
plugin.SetEnabled(true) // 默认启用
|
||||
}
|
||||
|
||||
pm.plugins[plugin.Name()] = plugin
|
||||
// 注册插件
|
||||
pm.registerPlugin(plugin)
|
||||
return nil
|
||||
}
|
||||
|
||||
// registerPlugin 注册插件到插件管理器
|
||||
func (pm *PluginManager) registerPlugin(plugin Plugin) {
|
||||
pluginType := plugin.Type()
|
||||
|
||||
// 将插件添加到按名称索引的映射
|
||||
pm.plugins[plugin.Name()] = plugin
|
||||
|
||||
// 将插件添加到按类型索引的映射
|
||||
if pm.pluginsByType[pluginType] == nil {
|
||||
pm.pluginsByType[pluginType] = make(map[string]Plugin)
|
||||
}
|
||||
pm.pluginsByType[pluginType][plugin.Name()] = plugin
|
||||
}
|
||||
|
||||
// RegisterPlugin 注册内置插件
|
||||
// 用于在不支持动态加载的平台上注册插件
|
||||
func (pm *PluginManager) RegisterPlugin(plugin Plugin) error {
|
||||
@@ -238,7 +259,8 @@ func (pm *PluginManager) RegisterPlugin(plugin Plugin) error {
|
||||
plugin.SetEnabled(true) // 默认启用
|
||||
}
|
||||
|
||||
pm.plugins[plugin.Name()] = plugin
|
||||
// 注册插件
|
||||
pm.registerPlugin(plugin)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -251,6 +273,36 @@ func (pm *PluginManager) GetPlugin(name string) (Plugin, bool) {
|
||||
return plugin, exists
|
||||
}
|
||||
|
||||
// GetPluginsByType 按类型获取插件
|
||||
func (pm *PluginManager) GetPluginsByType(pluginType PluginType) []Plugin {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
plugins := make([]Plugin, 0)
|
||||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||||
for _, plugin := range typePlugins {
|
||||
if plugin.IsEnabled() {
|
||||
plugins = append(plugins, plugin)
|
||||
}
|
||||
}
|
||||
}
|
||||
return plugins
|
||||
}
|
||||
|
||||
// GetAllPluginsByType 获取所有指定类型的插件,无论是否启用
|
||||
func (pm *PluginManager) GetAllPluginsByType(pluginType PluginType) []Plugin {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
plugins := make([]Plugin, 0)
|
||||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||||
for _, plugin := range typePlugins {
|
||||
plugins = append(plugins, plugin)
|
||||
}
|
||||
}
|
||||
return plugins
|
||||
}
|
||||
|
||||
// GetAllPlugins 获取所有插件
|
||||
func (pm *PluginManager) GetAllPlugins() []Plugin {
|
||||
pm.mu.RLock()
|
||||
@@ -275,6 +327,7 @@ func (pm *PluginManager) GetPluginInfos() []PluginInfo {
|
||||
Version: plugin.Version(),
|
||||
Description: plugin.Description(),
|
||||
Author: plugin.Author(),
|
||||
Type: plugin.Type(),
|
||||
Enabled: plugin.IsEnabled(),
|
||||
Config: pm.configs[name],
|
||||
}
|
||||
@@ -283,6 +336,29 @@ func (pm *PluginManager) GetPluginInfos() []PluginInfo {
|
||||
return infos
|
||||
}
|
||||
|
||||
// GetPluginInfosByType 按类型获取插件信息
|
||||
func (pm *PluginManager) GetPluginInfosByType(pluginType PluginType) []PluginInfo {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
infos := make([]PluginInfo, 0)
|
||||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||||
for name, plugin := range typePlugins {
|
||||
info := PluginInfo{
|
||||
Name: plugin.Name(),
|
||||
Version: plugin.Version(),
|
||||
Description: plugin.Description(),
|
||||
Author: plugin.Author(),
|
||||
Type: plugin.Type(),
|
||||
Enabled: plugin.IsEnabled(),
|
||||
Config: pm.configs[name],
|
||||
}
|
||||
infos = append(infos, info)
|
||||
}
|
||||
}
|
||||
return infos
|
||||
}
|
||||
|
||||
// EnablePlugin 启用插件
|
||||
func (pm *PluginManager) EnablePlugin(name string) error {
|
||||
pm.mu.Lock()
|
||||
@@ -345,6 +421,26 @@ func (pm *PluginManager) InitPlugins(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitPluginsByType 初始化指定类型的所有插件
|
||||
func (pm *PluginManager) InitPluginsByType(ctx context.Context, pluginType PluginType) error {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||||
for name, plugin := range typePlugins {
|
||||
if !plugin.IsEnabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
config := pm.configs[name]
|
||||
if err := plugin.Init(ctx, config); err != nil {
|
||||
return fmt.Errorf("初始化插件 %s 失败: %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartPlugins 启动所有插件
|
||||
func (pm *PluginManager) StartPlugins(ctx context.Context) error {
|
||||
pm.mu.RLock()
|
||||
@@ -362,6 +458,25 @@ func (pm *PluginManager) StartPlugins(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartPluginsByType 启动指定类型的所有插件
|
||||
func (pm *PluginManager) StartPluginsByType(ctx context.Context, pluginType PluginType) error {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||||
for name, plugin := range typePlugins {
|
||||
if !plugin.IsEnabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := plugin.Start(ctx); err != nil {
|
||||
return fmt.Errorf("启动插件 %s 失败: %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopPlugins 停止所有插件
|
||||
func (pm *PluginManager) StopPlugins(ctx context.Context) error {
|
||||
pm.mu.RLock()
|
||||
@@ -379,6 +494,25 @@ func (pm *PluginManager) StopPlugins(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopPluginsByType 停止指定类型的所有插件
|
||||
func (pm *PluginManager) StopPluginsByType(ctx context.Context, pluginType PluginType) error {
|
||||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||||
for name, plugin := range typePlugins {
|
||||
if !plugin.IsEnabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := plugin.Stop(ctx); err != nil {
|
||||
return fmt.Errorf("停止插件 %s 失败: %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPluginConfig 设置插件配置
|
||||
func (pm *PluginManager) SetPluginConfig(name string, config map[string]interface{}) error {
|
||||
pm.mu.Lock()
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -27,11 +28,12 @@ var Plugin = &LoggerPlugin{
|
||||
"1.0.0",
|
||||
"简单的日志记录插件",
|
||||
"开发者",
|
||||
plugin.PluginTypeUtils, // 设置插件类型为工具插件
|
||||
),
|
||||
}
|
||||
|
||||
// Init 初始化插件
|
||||
func (p *LoggerPlugin) Init(config map[string]interface{}) error {
|
||||
func (p *LoggerPlugin) Init(ctx context.Context, config map[string]interface{}) error {
|
||||
p.config = config
|
||||
|
||||
// 获取日志文件路径
|
||||
@@ -63,7 +65,7 @@ func (p *LoggerPlugin) Init(config map[string]interface{}) error {
|
||||
}
|
||||
|
||||
// Start 启动插件
|
||||
func (p *LoggerPlugin) Start() error {
|
||||
func (p *LoggerPlugin) Start(ctx context.Context) error {
|
||||
if p.logger == nil {
|
||||
return fmt.Errorf("插件未初始化")
|
||||
}
|
||||
@@ -74,7 +76,7 @@ func (p *LoggerPlugin) Start() error {
|
||||
}
|
||||
|
||||
// Stop 停止插件
|
||||
func (p *LoggerPlugin) Stop() error {
|
||||
func (p *LoggerPlugin) Stop(ctx context.Context) error {
|
||||
if p.logger != nil {
|
||||
p.logger.Println("日志插件正在停止")
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -27,13 +28,14 @@ var Plugin = &StatsPlugin{
|
||||
"1.0.0",
|
||||
"系统运行时统计插件",
|
||||
"开发者",
|
||||
plugin.PluginTypeUtils, // 设置为工具类插件
|
||||
),
|
||||
stats: make(map[string]int64),
|
||||
tickerStop: make(chan bool),
|
||||
}
|
||||
|
||||
// Init 初始化插件
|
||||
func (p *StatsPlugin) Init(config map[string]interface{}) error {
|
||||
func (p *StatsPlugin) Init(ctx context.Context, config map[string]interface{}) error {
|
||||
p.config = config
|
||||
|
||||
// 初始化统计指标
|
||||
@@ -49,7 +51,7 @@ func (p *StatsPlugin) Init(config map[string]interface{}) error {
|
||||
}
|
||||
|
||||
// Start 启动插件
|
||||
func (p *StatsPlugin) Start() error {
|
||||
func (p *StatsPlugin) Start(ctx context.Context) error {
|
||||
p.startTime = time.Now()
|
||||
|
||||
// 启动定时统计任务
|
||||
@@ -70,6 +72,9 @@ func (p *StatsPlugin) Start() error {
|
||||
case <-p.tickerStop:
|
||||
p.ticker.Stop()
|
||||
return
|
||||
case <-ctx.Done():
|
||||
p.ticker.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -79,7 +84,7 @@ func (p *StatsPlugin) Start() error {
|
||||
}
|
||||
|
||||
// Stop 停止插件
|
||||
func (p *StatsPlugin) Stop() error {
|
||||
func (p *StatsPlugin) Stop(ctx context.Context) error {
|
||||
if p.ticker != nil {
|
||||
p.tickerStop <- true
|
||||
}
|
||||
|
138
examples/plugin/plugins/storage/storage_plugin.go
Normal file
138
examples/plugin/plugins/storage/storage_plugin.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/darkit/goproxy/examples/plugin"
|
||||
)
|
||||
|
||||
// StoragePlugin 存储插件
|
||||
// 提供简单的文件存储功能
|
||||
type StoragePlugin struct {
|
||||
*plugin.BasePlugin // 嵌入基本插件结构
|
||||
storageDir string // 存储目录
|
||||
config map[string]interface{} // 配置
|
||||
mu sync.RWMutex // 读写锁
|
||||
}
|
||||
|
||||
// Plugin 导出的插件变量
|
||||
// 注意:变量名必须是Plugin,大小写敏感
|
||||
var Plugin = &StoragePlugin{
|
||||
BasePlugin: plugin.NewBasePlugin(
|
||||
"StoragePlugin",
|
||||
"1.0.0",
|
||||
"简单的文件存储插件",
|
||||
"开发者",
|
||||
plugin.PluginTypeStorage, // 设置插件类型为存储插件
|
||||
),
|
||||
}
|
||||
|
||||
// Init 初始化插件
|
||||
func (p *StoragePlugin) Init(ctx context.Context, config map[string]interface{}) error {
|
||||
p.config = config
|
||||
|
||||
// 获取存储目录路径
|
||||
storageDir, ok := config["storage_dir"].(string)
|
||||
if !ok {
|
||||
// 使用默认路径
|
||||
storageDir = "storage"
|
||||
}
|
||||
|
||||
// 确保存储目录存在
|
||||
if err := os.MkdirAll(storageDir, 0o755); err != nil {
|
||||
return fmt.Errorf("创建存储目录失败: %v", err)
|
||||
}
|
||||
|
||||
p.storageDir = storageDir
|
||||
fmt.Println("存储插件初始化完成,存储目录:", storageDir)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start 启动插件
|
||||
func (p *StoragePlugin) Start(ctx context.Context) error {
|
||||
if p.storageDir == "" {
|
||||
return fmt.Errorf("插件未初始化")
|
||||
}
|
||||
|
||||
fmt.Println("存储插件已启动")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop 停止插件
|
||||
func (p *StoragePlugin) Stop(ctx context.Context) error {
|
||||
fmt.Println("存储插件已停止")
|
||||
return nil
|
||||
}
|
||||
|
||||
// SaveFile 保存文件
|
||||
func (p *StoragePlugin) SaveFile(filename string, data []byte) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
if p.storageDir == "" {
|
||||
return fmt.Errorf("插件未初始化")
|
||||
}
|
||||
|
||||
filePath := filepath.Join(p.storageDir, filename)
|
||||
return os.WriteFile(filePath, data, 0o644)
|
||||
}
|
||||
|
||||
// LoadFile 加载文件
|
||||
func (p *StoragePlugin) LoadFile(filename string) ([]byte, error) {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
|
||||
if p.storageDir == "" {
|
||||
return nil, fmt.Errorf("插件未初始化")
|
||||
}
|
||||
|
||||
filePath := filepath.Join(p.storageDir, filename)
|
||||
return os.ReadFile(filePath)
|
||||
}
|
||||
|
||||
// DeleteFile 删除文件
|
||||
func (p *StoragePlugin) DeleteFile(filename string) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
if p.storageDir == "" {
|
||||
return fmt.Errorf("插件未初始化")
|
||||
}
|
||||
|
||||
filePath := filepath.Join(p.storageDir, filename)
|
||||
return os.Remove(filePath)
|
||||
}
|
||||
|
||||
// ListFiles 列出所有文件
|
||||
func (p *StoragePlugin) ListFiles() ([]string, error) {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
|
||||
if p.storageDir == "" {
|
||||
return nil, fmt.Errorf("插件未初始化")
|
||||
}
|
||||
|
||||
var files []string
|
||||
entries, err := os.ReadDir(p.storageDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
files = append(files, entry.Name())
|
||||
}
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// main 函数是必须的,但不会被调用
|
||||
func main() {
|
||||
// 不会被执行,仅用于编译插件
|
||||
}
|
@@ -84,10 +84,14 @@ func (d *DefaultDelegate) ParentProxy(req *http.Request) (*url.URL, error) {
|
||||
}
|
||||
|
||||
// WebSocketSendMessage websocket发送消息拦截
|
||||
func (h *DefaultDelegate) WebSocketSendMessage(ctx *Context, messageType *int, payload *[]byte) {}
|
||||
func (h *DefaultDelegate) WebSocketSendMessage(ctx *Context, messageType *int, payload *[]byte) {
|
||||
// 默认实现不做任何处理
|
||||
}
|
||||
|
||||
// WebSocketReceiveMessage websocket接收消息拦截
|
||||
func (h *DefaultDelegate) WebSocketReceiveMessage(ctx *Context, messageType *int, payload *[]byte) {}
|
||||
func (h *DefaultDelegate) WebSocketReceiveMessage(ctx *Context, messageType *int, payload *[]byte) {
|
||||
// 默认实现不做任何处理
|
||||
}
|
||||
|
||||
// ErrorLog 错误日志
|
||||
func (d *DefaultDelegate) ErrorLog(err error) {
|
||||
|
Reference in New Issue
Block a user