前言
Gin在golang领域是一个非常有名的框架,也是github上面star最高的一个框架,简单易学,效率还高。所以我们大部分web开发都会使用gin框架来进行开发。但是Gin框架里面有一个比较关键的知识点,其中一个就是中间件。(不只是Gin,很多其他框架也是有中间件的概念)
一、中间件的作用
- Web请求到到达我们定义的HTTP请求处理方法之前,拦截请求并进行相应处理(比如:权限验证,数据过滤等),这个可以类比为前置拦截器或前置过滤器,
- 在我们处理完成请求并响应客户端时,拦截响应并进行相应的处理(比如:添加统一响应部头或数据格式等),这可以类型为后置拦截器或后置过滤器。
二、洋葱模型
看上图,我们的中间件就相当于一层一层的洋葱。如果要到洋葱内部,需要一层一层的进入。同理,出来也是一层一层的出来。
三、上代码
知道中间件的作用以及洋葱模型,我们就可以开始撸代码了。
这里以golang作为示例代码。其实只要知道具体的作用,不管用什么代码都是可以徒手写中间件的。
package main
import (
"fmt"
"math"
)
const abortIndex = math.MaxInt8 / 2
// 中间件结构体
type Context struct {
Handlers []func(c *Context) //需要执行的方法切片
index int8 //偏移量
}
// 注册方法到中间件
func (this *Context) Use(f func(c *Context)) {
this.Handlers = append(this.Handlers, f)
}
// 执行下一个方法
func (this *Context) Next() {
if this.index < int8(len(this.Handlers)) {
this.index++
this.Handlers[this.index](this)
}
}
// 执行handlers里面的第一个方法
func (this *Context) Run() {
this.Handlers[0](this)
}
func (this *Context) GET(path string, f func(c *Context)) {
this.Handlers = append(this.Handlers, f)
}
// 终止
func (this *Context) Abort() {
this.index = abortIndex
}
//主方法
func main() {
c := &Context{}
c.Use(MiddlewareOne())
c.Use(MiddlewareTwo())
c.GET("/get", func(c *Context) {
fmt.Println("执行具体方法")
})
c.Run()
}
//中间件一
func MiddlewareOne() func(c *Context) {
return func(c *Context) {
fmt.Println("MiddlerOne Start")
c.Next()
fmt.Println("MiddlerOne End")
}
}
//中间件二
func MiddlewareTwo() func(c *Context) {
return func(c *Context) {
fmt.Println("MiddlerTwo Start")
c.Next()
fmt.Println("MiddlerTwo End")
}
}
//中间件三
func MiddlewareThree() func(c *Context) {
return func(c *Context) {
fmt.Println("MiddlerThree Start")
c.Next()
fmt.Println("MiddlerThree End")
}
}
大概讲一下代码的思路。首先我们定义一个中间件结构体,结构体里面分别有两个数据,一个是函数的切片。这个里面会存放所有的中间件函数,第二个是执行函数偏移量。也就是我们在一层层的剥洋葱时的层数,每深入一层,偏移量会加一。
这样我们在执行具体代码的时候的中间件执行顺序如下所示
那么我们控制台的输出结果就会如下
MiddlerOne Start
MiddlerTwo Start
执行具体方法
MiddlerTwo End
MiddlerOne End