Go语言中的gin框架【中间件】集合(七)

什么是中间件?

Gin框架是一种用于构建Web应用程序的Go语言框架。中间件是Gin框架中的一个重要概念,用于在请求处理过程中添加一些额外的功能或处理逻辑。

Gin框架中的中间件可以在请求被处理之前或之后执行一些操作。通常,中间件用于处理请求的验证、日志记录、错误处理等功能。Gin框架提供了一种简单而灵活的方式来定义和使用中间件。

中间件原理?

Gin框架的中间件原理可以简单概括为:通过函数包装器的方式,将中间件函数嵌入到请求处理链中,在请求被处理前或处理后执行一些额外的功能。

Gin框架中的中间件是一个函数,具有以下特点:

  1. 函数签名:中间件函数的签名为func(c *gin.Context),接受一个*gin.Context类型参数,表示请求上下文。

  2. 执行顺序:中间件函数按照注册的顺序执行。在请求被处理前,按照注册的顺序依次执行前置中间件;在请求被处理后,按照相反的顺序执行后置中间件。

  3. 请求处理链:Gin框架维护了一个请求处理链,将注册的中间件函数依次包装成处理链中的环节。每个环节都可以在请求被处理前或处理后执行一些操作。

  4. 上下文传递:中间件函数可以访问和修改请求上下文中的数据。Gin框架使用*gin.Context对象来表示请求上下文,中间件函数可以通过该对象来获取请求信息、设置响应信息等。

package main

import (
	"20230615/routers"
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
)

// 定义一个 userinfo 表单结构体对象
type UserInfo struct {
	UserName string `json:"username" form:"username"`
	Password string `json:"password" form:"password"`
	Age      string `json:"age" form:"age"`
}

// 路由中间件 在路由中走的 initMiddleWares
func initMiddleWares(c *gin.Context) {
	start := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----1", start)
	// c.Next()它在调用处理程序内部执行链中的挂起处理程序。Next只能在中间件内部使用
	c.Next()
	end := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----2", end)
}
func main() {
	// 定义一个路由引擎对象
	router := gin.Default()
	// 加载 渲染模板 全局
	router.LoadHTMLGlob("*templates/**/*")
	// 路由 get请求后 返回数据到模板渲染
	router.GET("/", initMiddleWares, func(c *gin.Context) {
		fmt.Println("------页面首页--------")
		c.String(200, "message")
	})

	routers.LoginRouterInit(router) // init router 初始化路由包

	router.Run(":8080")
}

输出的结果:

init middleware----路由-中间件----1 1687681850770421700
------页面首页--------
init middleware----路由-中间件----2 1687681850771422200

这里的就是中间件内部增加了 Next()方法挂起程序,让其继续执行。

通过ctrl+鼠标左键点击 ,可以追溯到源码内部查看,代码的其他方法;Abort()方法:Abort可防止调用挂起的处理程序。请注意,这不会停止当前处理程序。

package main

import (
	"20230615/routers"
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
)

// 定义一个 userinfo 表单结构体对象
type UserInfo struct {
	UserName string `json:"username" form:"username"`
	Password string `json:"password" form:"password"`
	Age      string `json:"age" form:"age"`
}

// 路由中间件 在路由中走的 initMiddleWares
func initMiddleWares(c *gin.Context) {
	start := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----1", start)
	// // c.Next()它在调用处理程序内部执行链中的挂起处理程序。Next只能在中间件内部使用
	// c.Next()
	// Abort可防止调用挂起的处理程序。请注意,这不会停止当前处理程序。
	c.Abort()
	end := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----2", end)
}
func main() {
	// 定义一个路由引擎对象
	router := gin.Default()
	// 加载 渲染模板 全局
	router.LoadHTMLGlob("*templates/**/*")
	// 路由 get请求后 返回数据到模板渲染
	router.GET("/", initMiddleWares, func(c *gin.Context) {
		fmt.Println("------页面首页--------")
		c.String(200, "message")
	})

	routers.LoginRouterInit(router) // init router 初始化路由包

	router.Run(":8080")
}

输出:

init middleware----路由-中间件----1 1687684669762450500
init middleware----路由-中间件----2 1687684669762450500

当然,演示的都是一些简单并且暂时,我们用到的方法,内部还有很多方法,就不一一演示了,可以自行查看方法的使用,追溯代码片段可以查看。

全局中间件代码演示:

func initMiddlewareOne(ctx *gin.Context) {
	fmt.Println("-one-中间件-initMiddlewareOne--1")
	// Next() 方法 调用该请求的剩余程序
	ctx.Next()
	fmt.Println("-one-中间件-initMiddlewareOne--2")

}
func initMiddlewareTwo(ctx *gin.Context) {
	fmt.Println("-two--中间件--initMiddlewareTwo--1")
	//终止调用该程序的剩余请求处理程序 abort()方法
	// ctx.Abort()
	ctx.Next()
	fmt.Println("-two--中间件--initMiddlewareTwo--2")
}


func main() {
	r := gin.Default()

	r.SetFuncMap(template.FuncMap{
		"UnitTime": UnitTime,
	})

	r.LoadHTMLGlob("*templates/**/*")

	r.Static("/static", "./static")

	// 通过 use() 方法全局注册中间件
	// r.Use(initMiddlewareOne, initMiddlewareTwo)



	r.GET("/", func(ctx *gin.Context) {
		fmt.Println("这是一个首页")
		ctx.HTML(http.StatusOK, "default/news.html", gin.H{
			"title": "这个是一个首页",
		})
		// ctx.String(200, "这是一个首页")
	})

	// 抽离了 路由,传入了 r;这样就是注册了路由,同时简化了入口文件的大小
	routers.DefaultRoutersInit(r)
	// 登陆路由 抽离 下一步,给路由内部的方法抽离成一个 控制器 controllers
	routers.LoginRoutersinit(r)

	r.Run(":8001")

}

终端输出:

// 中间件内部都是next方法
-one-中间件-initMiddlewareOne--1
-two--中间件--initMiddlewareTwo--1
-one-中间件-initMiddlewareOne--1
 -two--中间件--initMiddlewareTwo--2
-one-中间件-initMiddlewareOne--2
 -two--中间件--initMiddlewareTwo--2
 -one-中间件-initMiddlewareOne--2

以上就是演示就是路由中间件,在main.go 主入口文件下的使用,那么如何抽离出这个路由中间件initmiddlewares 呢?

这里如何给创建文件中间件init.go 注册到当前的路由中呢? 

package middlewares

import (
	"fmt"

	"github.com/gin-gonic/gin"
)

// 方法想要其他包也可以引用,必须要让
func InitMiddlewares(c *gin.Context) {
	url := c.Request.URL.String()

	fmt.Println("路由分组--中间件---", url)
}

在路由中直接引入包/ middlewares

使用具体方法如下:

package routers

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

	"20230619/controllers/login"
	"20230619/middlewares"
)

// 1. 如果我们要全局gold 使用,那么方法的首字母一定是大写
// 2. 路由内部的处理方法 进行抽离 使其成一个控制器 controller 「 首先, 」
func LoginRoutersinit(r *gin.Engine) {
	loginRouters := r.Group("/login", middlewares.InitMiddlewares)
	{
		loginRouters.GET("/", login.LoginControllers{}.Index)
		loginRouters.GET("/edit", login.LoginControllers{}.Edit)

	}
}

Gin框架中间件的一些常见操作:

注册中间件:在Gin框架中,可以通过调用Use方法来注册中间件。例如,router.Use(middleware1, middleware2)。

全局中间件:通过在路由器上注册中间件,可以将其应用于所有的请求。例如,router.Use(globalMiddleware)。

备注:这里延伸一下,关于路由引擎定义的时候,有两种,一个是New()和 default()两种方式;建议使用default方式创建路由引擎(这种方式的是默认路由引擎使用 Logger 和 Rovery 中间件的)。

同时,这两个中间件使用都是不同的作用,

         Logger 中间件将日志写入gin.DefaultWriter ,即,使用配置了 GIN_MODE=release。

         Recovery 中间件会 recover 任何 panic。 如果有panic 的话,会写入500 状态码值。

但是,使用 new()方法创建路由引擎,是一个全新没有任何中间件的。源码中就可以看出来:

路由级别中间件:可以在每个路由的处理函数中注册中间件。例如,router.GET("/api", routeMiddleware, handleFunc)。

定义完中间件方法,直接放入路由中,并且只对这个路由生效。

组级别中间件:可以在路由组中注册中间件,以应用于该组下的所有路由。例如,apiGroup := router.Group("/api", groupMiddleware)。

上下文中间件:中间件可以访问和修改请求上下文中的数据。例如,验证用户身份并将用户信息存储在上下文中,供后续处理函数使用。

错误处理中间件:可以定义一个中间件来捕获并处理请求处理过程中的错误。例如,记录错误日志或返回特定的错误响应。

链式中间件:可以将多个中间件连接起来,形成一个中间件链。例如,router.Use(middleware1, middleware2, middleware3)。

总的来说,中间件是Gin框架中非常有用的功能,可以帮助开发人员实现各种常见的功能和处理逻辑,使代码更加模块化和可维护。

希望对你学习有所帮助!

猜你喜欢

转载自blog.csdn.net/A_LWIEUI_Learn/article/details/131379589