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 |
|||
|
|||
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