前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go gin框架封装中间件之2:操作日志中间件

Go gin框架封装中间件之2:操作日志中间件

作者头像
王中阳Go
发布2022-10-26 14:49:33
1.9K0
发布2022-10-26 14:49:33
举报
文章被收录于专栏:Go语言学习专栏

‍需求说明

  1. 管理后台所有修改,添加,删除的操作都要记录
  2. 操作日志的统计不影响主程序的性能

需求分析

  1. 把相关代码封装成中间件,独立使用
  2. 合理使用goroutine,不影响主线程的性能

文档说明

  1. 基于golang语言开发
  2. 基于gin网络框架开发
  3. 基于MySQL5.8开发
  4. 把操作日志部分封装成中间件,在rourter文件中引用
  5. 非核心代码已省略,用3个竖着排列的点号.表示

数据库表结构设置

操作日志表

代码

中间件代码

代码分析

  1. 我们可以通过context直接获得请求方式和请求的url
  2. 无法直接获得返回信息,我们可以借助"ResponseWriter",运用拦截器的思想,把返回信息先截取到,再向下继续传递
  3. 像获得客户端ip这类方法封装到util中,方便灵活调用
  4. 我们无法将adminLogs()方法整体设置为goroutine,因为这样会将context的事件传递在新的协程中进行,无法正常传递。
  5. 所以我们再c.Next()事件传递之后,把json解析成结构体,以及保存操作日志到数据库的操作设置为使用goroutine协程操作
  6. 操作日志是没有比较记录查询操作的,所以我们把请求方式为GET的过滤掉
代码语言:javascript
复制
package middleware

//amdin操作日志
import (
    .
    .
    .
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"strings"
)

type bodyLogWriter struct {
	gin.ResponseWriter
	bodyBuf *bytes.Buffer
}

func (w bodyLogWriter) Write(b []byte) (int, error) {
	w.bodyBuf.Write(b)
	return w.ResponseWriter.Write(b)
}

var CommonLogInterceptor = commonLogInterceptor()

/*
1 使用goroutine和channel实现操作日志的入库保存,尽可能的不影响主程序
2 goroutine协程,提高并发量
3 channel通道
*/
func commonLogInterceptor() gin.HandlerFunc {
	return func(c *gin.Context) {
		adminLogs(c)
	}
}

//获得每次请求返回的code和message
func adminLogs(c *gin.Context) {
	if admin, _ := c.Get("admin"); admin != nil {
		method := c.Request.Method
		url := c.Request.URL.Path

		strBody := ""
		var blw bodyLogWriter
		blw = bodyLogWriter{bodyBuf: bytes.NewBufferString(""), ResponseWriter: c.Writer}
		c.Writer = blw
		c.Next()

		if method != "GET" {
			strBody = strings.Trim(blw.bodyBuf.String(), "\n")
			go func(strBody string) {
				var returnJson api.ReturnJson
				json.Unmarshal([]byte(strBody), &returnJson)
				message := fmt.Sprintf("%v", returnJson.Message)

				adminInfo := admin.(**service.RunningClaims)
				adminId := (*adminInfo).ID
				adminName := (*adminInfo).Account

				var log = model.AdminLog{
					AdminId:   adminId,
					AdminName: adminName,
					Method:    method,
					Url:       url,
					Ip:        util.RemoteIP(c.Request),
					Code:      returnJson.Code,
					Message:   message,
				}

				model.CreateLog(log)
			}(strBody)
		}
	}
}

model层代码

代码语言:javascript
复制
package model

type AdminLog struct {
	ID int `json:"id"`
	AdminId uint `json:"admin_id"`
	AdminName string `json:"admin_name"`
	Method string `json:"method"`
	Ip string `json:"ip"`
	Url string `json:"url"`
	Code int `json:"code"`
	Message string `json:"message"`
}

func CreateLog(log AdminLog)  {
	DB.Create(&log)
}

路由代码

代码语言:javascript
复制
package server

import (
	.
	.
	.
	"os"
	"github.com/gin-gonic/gin"
)

// NewRouter 路由配置
func NewRouter() *gin.Engine {
	r := gin.Default()

	// 其他中间件
	.
	.
	.
	// 路由
	v1 := r.Group("/api/v1")
	{
		v1.POST("login", api.Login)
		auth := v1.Group("")
		//登录校验中间件
		auth.Use(middleware.AuthRequired())
		//关键代码:权限角色校验
		auth.Use(middleware.AuthCheckMiddleware)
		//操作日志
		auth.Use(middleware.CommonLogInterceptor)
		{
            .
            .
            .
			// 获取所有学校
			{
				auth.GET("/school/", api.GetSchoolInfo)
			}
			.
			.
			.
		}

	}
	return r
}

总结

  1. 以上则是我的实现思路
  2. 还有另外一种思路,计划已消息队列的方式实现,发送通知进行日志的报错

相关文章

  1. GO部分打算做成一个系列,最终把封装好的代码开源出来
  2. 上一篇:你用Go写过中间件吗?带你用Gin实现【用户角色权限管理中间件】

联系我

如果有更好的实现思路,或者项目合作,可以私信我或者在文章底部留言。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员升级打怪之旅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ‍需求说明
  • 需求分析
  • 文档说明
  • 数据库表结构设置
    • 操作日志表
    • 代码
      • 中间件代码
        • 代码分析
      • model层代码
        • 路由代码
        • 总结
        • 相关文章
        • 联系我
        相关产品与服务
        消息队列 TDMQ
        消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档