diff --git a/server/main.go b/server/main.go index ae8f256d68cd8ad04280b2c8828312e17474ebb5..3abcd0c1a79c1c46e3553a644444c52c038c7a9b 100644 --- a/server/main.go +++ b/server/main.go @@ -1,33 +1,38 @@ package main -import ( - "gin-vue-admin/core" - "gin-vue-admin/global" - "gin-vue-admin/initialize" -) +//import ( +// "gin-vue-admin/core" +// "gin-vue-admin/global" +// "gin-vue-admin/initialize" +//) +// +////go:generate go env -w GO111MODULE=on +////go:generate go env -w GOPROXY=https://goproxy.cn,direct +////go:generate go mod tidy +////go:generate go mod download +// +//// @title Swagger Example API +//// @version 0.0.1 +//// @description This is a sample Server pets +//// @securityDefinitions.apikey ApiKeyAuth +//// @in header +//// @name x-token +//// @BasePath / +//func main() { +// global.GVA_VP = core.Viper() // 初始化Viper +// global.GVA_LOG = core.Zap() // 初始化zap日志库 +// global.GVA_DB = initialize.Gorm() // gorm连接数据库 +// initialize.Timer() +// if global.GVA_DB != nil { +// initialize.MysqlTables(global.GVA_DB) // 初始化表 +// // 程序结束前关闭数据库链接 +// db, _ := global.GVA_DB.DB() +// defer db.Close() +// } +// core.RunWindowsServer() +//} -//go:generate go env -w GO111MODULE=on -//go:generate go env -w GOPROXY=https://goproxy.cn,direct -//go:generate go mod tidy -//go:generate go mod download +var Plugin plugin -// @title Swagger Example API -// @version 0.0.1 -// @description This is a sample Server pets -// @securityDefinitions.apikey ApiKeyAuth -// @in header -// @name x-token -// @BasePath / -func main() { - global.GVA_VP = core.Viper() // 初始化Viper - global.GVA_LOG = core.Zap() // 初始化zap日志库 - global.GVA_DB = initialize.Gorm() // gorm连接数据库 - initialize.Timer() - if global.GVA_DB != nil { - initialize.MysqlTables(global.GVA_DB) // 初始化表 - // 程序结束前关闭数据库链接 - db, _ := global.GVA_DB.DB() - defer db.Close() - } - core.RunWindowsServer() +type plugin struct { } diff --git a/server/router/example/plugin.go b/server/router/example/plugin.go new file mode 100644 index 0000000000000000000000000000000000000000..c2b61fef37ed208df921d13503e893938306181b --- /dev/null +++ b/server/router/example/plugin.go @@ -0,0 +1,16 @@ +package example + +import "github.com/gin-gonic/gin" + +type Plugin struct { +} + +func (*Plugin) Register(group *gin.RouterGroup) { + group.GET("hello", func(context *gin.Context) { + context.JSON(200, "hello world") + }) +} + +func (*Plugin) RouterPath() string { + return "group" +} diff --git a/server/utils/plugin/plugin.go b/server/utils/plugin/plugin.go new file mode 100644 index 0000000000000000000000000000000000000000..f5e7a5360136b0c6061f828346bb2edb7b5ef4d8 --- /dev/null +++ b/server/utils/plugin/plugin.go @@ -0,0 +1,41 @@ +package plugin + +import ( + "plugin" + "sync" + + "github.com/gin-gonic/gin" +) + +const ( + OnlyFuncName = "Plugin" +) + +var ManagementPlugin = managementPlugin{mp: make(map[string]*plugin.Plugin)} + +type managementPlugin struct { + mp map[string]*plugin.Plugin + sync.Mutex +} + +func (m *managementPlugin) SetPlugin(key string, p *plugin.Plugin) { + m.Lock() + defer m.Unlock() + m.mp[key] = p +} + +func (m *managementPlugin) GetPlugin(key string) (p *plugin.Plugin, ok bool) { + m.Lock() + defer m.Unlock() + p, ok = m.mp[key] + return +} + +// Plugin 插件模式接口化 +type Plugin interface { + // Register 注册路由 + Register(group *gin.RouterGroup) + + // RouterPath 用户返回注册路由 + RouterPath() string +} diff --git a/server/utils/plugin/plugin_uinx.go b/server/utils/plugin/plugin_uinx.go new file mode 100644 index 0000000000000000000000000000000000000000..69a9d1b6ee8c8a73cbcaa9b1d70e7d04485d5e22 --- /dev/null +++ b/server/utils/plugin/plugin_uinx.go @@ -0,0 +1,69 @@ +//+build !windows + +package plugin + +import ( + "errors" + "fmt" + "io/fs" + "io/ioutil" + "os" + "path/filepath" + "plugin" +) + +// LoadPlugin 加载插件 传入path +func LoadPlugin(path string) error { + path, err := filepath.Abs(path) + if err != nil { + return err + } + fileInfo, err := os.Stat(path) + if err != nil { + return err + } + if fileInfo.IsDir() { + fileSlice, err := ioutil.ReadDir(path) + if err != nil { + return err + } + for _, ff := range fileSlice { + if !ff.IsDir() && filepath.Ext(ff.Name()) == ".so" { + if err = loadPlugin(path, ff); err != nil { + return err + } + } else if ff.IsDir() { + _ = LoadPlugin(filepath.Join(path, ff.Name())) + } + } + return nil + } else { + return loadPlugin(path, fileInfo) + } +} + +func loadPlugin(path string, f fs.FileInfo) error { + if filepath.Ext(f.Name()) == ".so" { + fPath := filepath.Join(path, f.Name()) + // 加载插件 + p, err := plugin.Open(fPath) + if err != nil { + fmt.Println("loadPlugin err ", err) + return err + } + // 判断是否满足协议 + // 要满足 OnlyFuncName && 实现 Plugin 接口 + if v, err := p.Lookup(OnlyFuncName); err != nil { + fmt.Println("loadPlugin err ", err) + return err + } else if _, ok := v.(Plugin); !ok { + fmt.Println("loadPlugin err ", fmt.Sprintf("path:%s 没有实现 %s 接口", filepath.Base(fPath), OnlyFuncName)) + return errors.New("没有实现指定接口") + } else { + + } + fmt.Println("loadPlugin add ", filepath.Base(fPath)) + ManagementPlugin.SetPlugin(filepath.Base(fPath), p) + } + return nil +}