Gin中间件

Gin中间件

1 中间件简介

/*
	Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。

*/

在gin中的Default的方法中已经有两个中间件了:

// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
    debugPrintWARNINGDefault()
    engine := New()
    engine.Use(Logger(), Recovery())// 日志和异常恢复中间件
    return engine
}

如果我们想创建一个没有任何中件的router可以通过New方法:

router := gin.New()

然后可以在这个router中使用中间件:

func main() {
    // 创建一个不包含中间件的路由器
    r := gin.New()

    // 全局中间件
    // 使用 Logger 中间件
    r.Use(gin.Logger())

    // 使用 Recovery 中间件
    r.Use(gin.Recovery())

    // 路由添加中间件,可以添加任意多个
    r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

    // 路由组中添加中间件
    // authorized := r.Group("/", AuthRequired())
    // exactly the same as:
    authorized := r.Group("/")
    // per group middleware! in this case we use the custom created
    // AuthRequired() middleware just in the "authorized" group.
    authorized.Use(AuthRequired())
    {
        authorized.POST("/login", loginEndpoint)
        authorized.POST("/submit", submitEndpoint)
        authorized.POST("/read", readEndpoint)

        // nested group
        testing := authorized.Group("testing")
        testing.GET("/analytics", analyticsEndpoint)
    }

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

2 路由添加中间件

package routers

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

func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", func(context *gin.Context) {
			fmt.Println("欢迎来到api")
		}, api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}
/*
	这时候当我们访问 127.0.0.1:8000/api 时 就会先触发
 	func(context *gin.Context) {
			fmt.Println("欢迎来到api")
	}
	然后才是我们的业务逻辑代码,在业务逻辑代码之前我们可以加无数个中间件
*/

// 也可以这么写
package routers

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

func InitMiddleware(c *gin.Context) {
	fmt.Println("欢迎来到api")
}
func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", InitMiddleware, api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}

/* 
	需要注意的是 业务逻辑必须放在最后才行
*/

3 如果想在业务逻辑处理完后再执行一些操作怎么办 ------- c.Next()

package routers

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

func InitMiddleware(c *gin.Context) {
	fmt.Println("欢迎来到api")
	c.Next()
	fmt.Println("请求结束")
}
func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", InitMiddleware, api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}
当我们的中间件加入了c.Next()后
当我们访问  127.0.0.1:8000/api 时
整个运行流程就变为
先执行 fmt.Println("欢迎来到api")

然后是 api.ApiController{}.Api 执行我们的业务逻辑

最后是执行c.Next()后面的代码  fmt.Println("请求结束")

3.1 统计请求处理时间

package routers

import (
	"awesomeProject/gin/controllers/api"
	"fmt"
	"github.com/gin-gonic/gin"
	"time"
)

func InitMiddleware(c *gin.Context) {
	start := time.Now().UnixNano()
	c.Next()
	end := time.Now().UnixNano()
	fmt.Printf("使用了 %vms", end-start)
}
func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", InitMiddleware, api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}

4 c.Abort()

package routers

import (
	"awesomeProject/gin/controllers/api"
	"fmt"
	"github.com/gin-gonic/gin"
	"time"
)

func InitMiddleware(c *gin.Context) {
	start := time.Now().UnixNano()
	//c.Next()
	c.Abort()
	end := time.Now().UnixNano()
	fmt.Printf("使用了 %vms", end-start)
}
func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", InitMiddleware, api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}
整体运行流程
当我们的中间件加入了c.Abort()后
当我们访问  127.0.0.1:8000/api 时
整个运行流程就变为
先执行 start := time.Now().UnixNano()

然后是 
end := time.Now().UnixNano()
fmt.Printf("使用了 %vms", end-start)

并不会去执行我们的业务逻辑代码

5 多个中间件的执行

package routers

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

func InitMiddlewareOne(c *gin.Context) {
	fmt.Println("第一个中间件")
	c.Next()
	fmt.Println("第一个中间件结束")
}

func InitMiddlewareTwo(c *gin.Context) {
	fmt.Println("第二个中间件")
	c.Next()
	fmt.Println("第二个中间件结束")
}
func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", InitMiddlewareOne, InitMiddlewareTwo, api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}

pFFBhYq.png

6 全局中间件

全局中间件需要在main.go中配置

package main

import (
	"awesomeProject/gin/routers"
	"encoding/xml"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)


func InitMiddlewareOne(c *gin.Context) {
	fmt.Println("第一个中间件")
	c.Next()
	fmt.Println("第一个中间件结束")
}

func InitMiddlewareTwo(c *gin.Context) {
	fmt.Println("第二个中间件")
	c.Next()
	fmt.Println("第二个中间件结束")
}
func main() {
	r := gin.Default()
	r.Use(InitMiddlewareOne)   // 添加中间件 单个中间件
    r.Use(InitMiddlewareOne, InitMiddlewareTwo) // 多个中间件 多个中间件的运行流程与上面的一样
	routers.AdminRoutersInit(r)
	routers.ApiRoutersInit(r)
	routers.DefaultRoutersInit(r)
	r.Run(":8000") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

7 路由分组中配置中间件

第一种方法

package routers

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

func InitMiddlewareOne(c *gin.Context) {
	fmt.Println("第一个中间件")
	c.Next()
	fmt.Println("第一个中间件结束")
}

func InitMiddlewareTwo(c *gin.Context) {
	fmt.Println("第二个中间件")
	c.Next()
	fmt.Println("第二个中间件结束")
}
func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	apiRouters.Use(InitMiddlewareOne) // 直接使用Use,配置中间件
	{
		apiRouters.GET("/",api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}
package routers

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

func InitMiddlewareOne(c *gin.Context) {
	fmt.Println("第一个中间件")
	c.Next()
	fmt.Println("第一个中间件结束")
}

func InitMiddlewareTwo(c *gin.Context) {
	fmt.Println("第二个中间件")
	c.Next()
	fmt.Println("第二个中间件结束")
}
func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api",InitMiddlewareOne // 直接在后面加中间件
	{
		apiRouters.GET("/", api.ApiController{}.Api)
		apiRouters.GET("/userlist", api.ApiController{}.ApiUserList)
		apiRouters.GET("/plist", api.ApiController{}.ApiPlist)
		apiRouters.GET("/cart", api.ApiController{}.ApiCart)
	}
}

8 中间件和对应控制器之间共享数据

使用 c.Set() 设置数据

获取数据 c.Get() 
posted @ 2024-01-17 11:01  春游去动物园  阅读(4)  评论(0编辑  收藏  举报