songzhibin97
3 years ago
4 changed files with 159 additions and 28 deletions
-
61server/main.go
-
16server/router/example/plugin.go
-
41server/utils/plugin/plugin.go
-
69server/utils/plugin/plugin_uinx.go
@ -1,33 +1,38 @@ |
|||||
package main |
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 { |
||||
} |
} |
@ -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" |
||||
|
} |
@ -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 |
||||
|
} |
@ -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 |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue