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