Gin学习笔记--中间件的编写与使用

中间件

在web应用服务中,完整的一个业务处理在技术上包括客户端操作,服务端处理,返回处理结果给客户端三个步骤。

在实际的业务开发和处理中,会有更复杂的业务和需求场景。一个完整的系统可能要包含鉴权认证,权限管理,安全检查,日志记录等多维度的系统支持。

鉴权认证,权限管理,安全检查,日志记录等这些保障和支持系统业务属于全系统的业务,和具体的系统业务没有关联,对于系统中的所有业务都适用。

由此,在业务开发中,为了更好的梳理系统架构,可以将上述描述所涉及的一些通用业务单独抽离并进行开发,然后以插件化的形式进行对接。这种方式即保证了系统功能的完整,同时又

有效的将具体业务和系统功能进行解耦。

这种通用业务独立开发并灵活配置使用的组件,一般称之为“中间件”。因为其位于服务器和实际业务处理程序之间。其含义就是相当于在请求和具体的业务逻辑处理之间增加某些操作。

这种额外田间的方式不会影响编码效率,也不会侵入到框架中。

Gin的中间件

在gin中,中间件称之为middleware,中间件的类型定义如下:

type HadnleFunc func(*Context)

HandleFunc是一个函数类型,接收一个Context参数,用于编写程序处理函数并返回HandleFunc类型,作为中间件的定义

中间件Use用法

自定义中间件

中间件的类型是函数,有两条标准:

  1.func函数

  2.返回值类型为HandleFunc

例子:定义一个中间件,在处理请求时,为了方便代码调试,通常将请求的一些信息打印出来。有了中间件以后,为了避免多次重复代码编写,使用统一的中间件来完成。

定义一个RequestInfos中间件,在该中间件中打印请求的路径和请求方法。代码如下:

package main

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

func RequestInfos() gin.HandlerFunc {
    return func(context *gin.Context) {
        path := context.FullPath()
        method := context.Request.Method
        fmt.Println("请求路径:", path)
        fmt.Println("请求方法:", method)
    }
}

func main() {
    engine := gin.Default()
    engine.Use(RequestInfos())
    engine.GET("/query", func(ctx *gin.Context) {
        ctx.JSON(200, map[string]interface{}{
            "code":    1,
            "message": ctx.FullPath(),
        })
    })
    engine.Run()
}

运行截图:

 

 context.Next函数

在上文定义的中间件RequestInfos中,打印了请求路径和请求方法,接着去执行了正常的业务处理函数。如果我们想要输出业务处理结果的信息,可以使用context.Next函数来实现。

context.Next函数可以将中间件代码的执行顺序一分为二,Next函数调用之前的代码在请求处理之前,当程序执行到context.Next时,会中断向下执行,转而先去执行具体的业务逻辑,执行完业务逻辑处理函数之后,程序会再次回到context.Next处,继续执行中间件后续的代码。具体用法如下:

package main

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

func RequestInfos() gin.HandlerFunc {
    return func(context *gin.Context) {
        path := context.FullPath()
        method := context.Request.Method
        fmt.Println("请求路径:", path)
        fmt.Println("请求方法:", method)
        context.Next()
        fmt.Println("状态码:", context.Writer.Status())
    }
}

func main() {
    engine := gin.Default()
    engine.Use(RequestInfos())
    engine.GET("/query", func(ctx *gin.Context) {
        fmt.Println("-------------")
        ctx.JSON(201, map[string]interface{}{
            "code":    1,
            "message": ctx.FullPath(),
        })
    })
    engine.Run()
}

 

posted @ 2023-03-12 15:38  99号的格调  阅读(151)  评论(0编辑  收藏  举报