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() }