gin框架内容(三)--中间件
Gin框架允许开发者在处理请求的过程中,加入用户自己的函数。这个函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等
即比如,如果访问一个网页的话,不管访问什么路径都需要进行登录,此时就需要为所有路径的处理函数进行统一一个中间件
Gin中的中间件必须是一个gin.HandlerFunc类型
一、中间件的设置
1.1为路由单独注册中间件
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func indexHandler(c *gin.Context) {
fmt.Println("index.....")
c.JSON(http.StatusOK, gin.H{
"msg": "index",
})
}
// 定义一个中间件
func m1(c *gin.Context) {
fmt.Println("m1 in.........")
start := time.Now()
c.Next() //调用后续的处理函数,即indexHandler
//Since是一个函数,传入的参数是(t Time),返回值是 Duration
//Duration是一个自定义类型,即: type Duration int64
cost := time.Since(start) //从开始时间到现在花费的时间
fmt.Println(cost)
fmt.Println("m1 out.........")
}
func main() {
r := gin.Default()
// m1处于indexHandler函数的前面,请求来之后,先走m1,再走index
r.GET("/index", m1, indexHandler)
_ = r.Run()
}
1.2为全局路由注册1个中间件
定义的全局中间件,下面的每个路由调用都是经过这个全局中间件
1.3为全局路由注册2个中间件【多个中间件也是这样的思路】
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func indexHandler(c *gin.Context) {
fmt.Println("index.....")
c.JSON(http.StatusOK, gin.H{
"msg": "index",
})
}
// 定义一个中间件m1
func m1(c *gin.Context) {
fmt.Println("m1 in.........")
start := time.Now()
c.Next()
cost := time.Since(start)
fmt.Println(cost)
fmt.Println("m1 out.........")
}
// 定义一个中间件m2
func m2(c *gin.Context) {
fmt.Println("m2 in.........")
c.Next()
fmt.Println("m2 out.........")
}
func main() {
r := gin.Default()
//确定中间件中间的关系
r.Use(m1, m2)
r.GET("/index", indexHandler)
r.GET("/shop", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "shop",
})
})
r.GET("/user", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "user",
})
})
_ = r.Run()
}
从上面的打印关系可以看出,先通过第一个中间件M1的“
c.Next()的前半部分,然后在到M2,最后到index,然后在执行c.Next()的后半部分,
这就是一个中间件的链条
1.4中间件的后面路由停止执行
1.4.1终止执行1
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func indexHandler(c *gin.Context) {
fmt.Println("index.....")
c.JSON(http.StatusOK, gin.H{
"msg": "index",
})
}
// 定义一个中间件
func m1(c *gin.Context) {
fmt.Println("m1 in.........")
start := time.Now()
c.Next()
cost := time.Since(start)
fmt.Println(cost)
fmt.Println("m1 out.........")
}
// 定义一个中间件
func m2(c *gin.Context) {
fmt.Println("m2 in.........")
c.Abort() //阻止调用后续的处理函数
fmt.Println("m2 out.........")
}
func main() {
r := gin.Default()
r.Use(m1, m2)
r.GET("/index", indexHandler)
r.GET("/shop", func(c *gin.Context) {
fmt.Println("1111")
c.JSON(http.StatusOK, gin.H{
"msg": "shop",
})
})
r.GET("/user", func(c *gin.Context) {
fmt.Println("222222222")
c.JSON(http.StatusOK, gin.H{
"msg": "user",
})
})
_ = r.Run()
}
因为m2中有个“
c.Abort() //阻止调用后续的处理函数
”阻止后续内容执行,到这里就是返回了,根本执行不到后续路由信息
1.4.2终止执行2 return
1.5数据传递
在中间件里做一些操作,然后在处理函数里拿到或者其它的中间件里拿到对应的数据
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func indexHandler(c *gin.Context) {
fmt.Println("index.....")
//Get是*Context的方法 传入的参数是(key string) ,返回值是(value interface{}, exists bool)
name, ok := c.Get("name")
if !ok {
name = "匿名用户"
}
c.JSON(http.StatusOK, gin.H{
"msg": name,
})
}
// 定义一个中间件
func m1(c *gin.Context) {
fmt.Println("m1 in.........")
start := time.Now()
c.Next()
cost := time.Since(start)
fmt.Println(cost)
name, ok := c.Get("name")
if !ok {
name = "匿名用户"
}
fmt.Println(name)
fmt.Println("m1 out.........")
}
// 定义一个中间件
func m2(c *gin.Context) {
fmt.Println("m2 in.........")
c.Set("name", "tom")
fmt.Println("m2 out.........")
}
func main() {
r := gin.Default()
r.Use(m1, m2)
r.GET("/index", indexHandler)
_ = r.Run()
}