Categories: GoFrame 教程

GoFrame 接口开发-回调处理

自定义回调处理是最常见的接口开发实现,我们往往只需要对接口中的部分实现进行替换修改,以在原有的实现逻辑中注入自定义的逻辑实现。我们来看一个自定义回调处理的示例,我们需要将所有执行的​SQL​语句记录到​monitor​表中,以方便于进行​SQL​审计。

为简化示例编写,我们这里实现了一个自定义的​MySQL​驱动,该驱动继承于​gdb​模块中已经实现的​DriverMysql​,并按照需要修改覆盖相应的接口方法。由于所有的​SQL​语句执行必定会通过​DoQuery​或者​DoExec​接口,因此我们在自定义的驱动中实现并覆盖这两个接口方法即可。

package driver

import (
 "context"
 "database/sql"
 "github.com/gogf/gf/v2/database/gdb"
 "github.com/gogf/gf/v2/os/gtime"
)

// MyDriver is a custom database driver, which is used for testing only.
// For simplifying the unit testing case purpose, MyDriver struct inherits the mysql driver
// gdb.DriverMysql and overwrites its functions DoQuery and DoExec.
// So if theres any sql execution, it goes through MyDriver.DoQuery/MyDriver.DoExec firstly
// and then gdb.DriverMysql.DoQuery/gdb.DriverMysql.DoExec.
// You can call it sql "HOOK" or "HiJack" as your will.
type MyDriver struct {
 *gdb.DriverMysql
}

var (
 // customDriverName is my driver name, which is used for registering.
 customDriverName = "MyDriver"
)

func init() {
 // It here registers my custom driver in package initialization function "init".
 // You can later use this type in the database configuration.
 if err := gdb.Register(customDriverName, &MyDriver{}); err != nil {
  panic(err)
 }
}

// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *MyDriver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
 return &MyDriver{
  &gdb.DriverMysql{
   Core: core,
  },
 }, nil
}

// DoQuery commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoQuery(ctx context.Context, link gdb.Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
 tsMilli := gtime.TimestampMilli()
 rows, err = d.DriverMysql.DoQuery(ctx, link, sql, args...)
 link.Exec(
  "INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
  gdb.FormatSqlWithArgs(sql, args),
  gtime.TimestampMilli()-tsMilli,
  gtime.Now(),
  err,
 )
 return
}

// DoExec commits the query string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoExec(ctx context.Context, link gdb.Link, sql string, args ...interface{}) (result sql.Result, err error) {
 tsMilli := gtime.TimestampMilli()
 result, err = d.DriverMysql.DoExec(ctx, link, sql, args...)
 link.Exec(
  "INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
  gdb.FormatSqlWithArgs(sql, args),
  gtime.TimestampMilli()-tsMilli,
  gtime.Now(),
  err,
 )
 return
}

// DoFilter is a hook function, which filters the sql and its arguments before its committed to underlying driver.
// The parameter `link` specifies the current database connection operation object. You can modify the sql
// string `sql` and its arguments `args` as you wish before theyre committed to driver.
func (d *MyDriver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) {
 //Filter sql Step1
 sql_new := gstr.Replace(sql, "
", "")

 //Filter sql Step2
 sql_new = gstr.Replace(sql_new, " ", "")
 //... Filter what you want ...

 //Filter args Step1
 for _, v := range args {
  switch v.(type) {
  case gdb.Map:
   //Do it what you wan
  case string:
   //Do it what you wan
  }
 }
 return sql_new, args, nil
}


func (d *MyDriver) ConvertDataForRecord(ctx context.Context, data interface{}) map[string]interface{} {
 //this hook is convert data to map[string]interface{}
 result := make(map[string]interface{}, 0)

 //like this
 switch data.(type) {
 case gdb.Map:
  result = gconv.Map(data)
 case gdb.List:
  for k, v := range data.(gdb.List) {
   result[strconv.Itoa(k)] = gconv.Map(v)
  }
  //case other type,do it what you want
 }
 return result
}

我们看到,这里在包初始化方法​init​中使用了​gdb.Register("MyDriver", &MyDriver{})​来注册了了一个自定义名称的驱动。我们也可以通过​gdb.Register("mysql", &MyDriver{})​来覆盖已有的框架​mysql​驱动为自己的驱动。

驱动名称​mysql​为框架默认的​DriverMysql​驱动的名称。

由于这里我们使用了一个新的驱动名称​MyDriver​,因此在​gdb​配置中的​type​数据库类型时,需要填写该驱动名称。以下是一个使用配置的示例:

database:
  default:
  - link: "MyDriver:root:12345678@tcp(127.0.0.1:3306)/user"

andy

前端小白,在Web176教程网这个平台跟大家一起学习,加油!

Share
Published by
andy

Recent Posts

vue:页面注入js修改input值

一般会直接这样写: let z…

3 小时 ago

聊聊vue3中的defineProps

在Vue 3中,defineP…

1 周 ago

在 Chrome 中删除、允许和管理 Cookie

您可以选择删除现有 Cooki…

2 周 ago

自定义指令:聊聊vue中的自定义指令应用法则

今天我们来聊聊vue中的自定义…

3 周 ago

聊聊Vue中@click.stop和@click.prevent

一起来学下聊聊Vue中@cli…

4 周 ago

Nginx 基本操作:启动、停止、重启命令。

我们来学习Nginx基础操作:…

1 月 ago