什么是中间件
中间件是一个十分宽泛的概念,在不同领域表示不同的含义,其中在bs/cs软件编程框架中,中间件可以理解为一些用于解耦业务和非业务代码的钩子函数,这些函数可以适用于所有或者部分请求。
中间件的原理和钩子函数类似,在框架层面,程序运行到某个阶段自动执行预设值的函数,运行完后再回到跳出的那个阶段继续执行原函数。
在bs/cs开发中,为了在主体函数前后执行一些通用操作,常见的写法会预设一些钩子比如beforeXxxFunc、afterXxxFunc,但这毕竟只有两个函数并且是针对全局请求,想要实现部分钩子函数针对某些请求就得做一些额外的业务外的操作来达到目的。gin框架的中间件就解决了这些痛点。
中间件原理
原理1:每一条请求就是处理自己所挂载的所有中间件和唯一主体函数。
普通的钩子函数如图所示:
优点:解耦了业务和非业务代码,非业务代码做到了统一封装使用。
缺点:如果想针对某些主体函数不执行或者执行其他beforeFunction需要额外修改框架逻辑。
gin框架中间件如图:
优点:
- 利用中间件解耦了业务和非业务代码。
- 每个中间件可以复用。
- 每个主体函数也可以单独设置一个或者多个中间件。
原理2:洋葱模型。
洋葱模型,如图所示:
beforeFunc1和afterFunc1即是中间件1;afterFunc2和afterFunc2即是中间件2。
请求到来时从最外层开始执行中间件1,然后进入第二层,依次执行完所有中间件最后到达主体函数,接着再一层一层的往外走再次执行中间件2...中间件1...最后返回,也有点像栈的概念。
gin中中间件的实现
步骤1
首先,gin把中间件和主体函数统一定义为一个handleFunc。
源码:gin.go
不管是用use()方法注册中间件,还是用restful注册主体函数,类型都是HandlerFunc。
源码:routergroup.go
步骤2
把所有handleFunc装入一个数组或者叫handleChain的东西。
步骤3
从handleChain的第一个元素开始执行,中间使用c.next、c.Abort等函数来进行流程控制。
手动实现一个简单版本的中间件
运行结果: