iris中的中间件调用顺序
有一篇文章写得不错:「Go框架」深入理解web框架的中间件运行机制 - 知乎 (zhihu.com)
我这里只是写一个简单的demo来观察一下,代码如下:
package main import ( "fmt" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/middleware/logger" "github.com/kataras/iris/v12/middleware/recover" ) func GlobalMidware(ctx iris.Context) { // 打印消息1 fmt.Println("GlobalMidware: before call next") ctx.Next() //调用下一级handler fmt.Println("GlobalMidware: after call next") } // 自定义中间件1:打印消息1 func Middleware1(ctx iris.Context) { // 打印消息1 fmt.Println("Middleware 1: before call next") ctx.Next() //调用下一级handler fmt.Println("Middleware 1: after call next") } // 自定义中间件2:打印消息2 func Middleware2(ctx iris.Context) { // 打印消息2 fmt.Println("Middleware 2: before call next") ctx.Next() //调用下一级handler fmt.Println("Middleware 2: after call next") } func MyHandler(ctx iris.Context) { fmt.Println("Handler: Hello from handler") ctx.HTML("<h1>Hello, World!</h1>") } func AdminHelloHandler(ctx iris.Context) { fmt.Println("AdminHelloHandler: Hello from handler") ctx.HTML("<h1>Hello, Admin!</h1>") } func AdminMidware1(ctx iris.Context) { // 打印消息2 fmt.Println("AdminMidware: before call next") ctx.Next() //调用下一级handler fmt.Println("AdminMidware: after call next") } func AdminRouteMidware(ctx iris.Context) { // 打印消息2 fmt.Println("AdminRouteMidware: before call next") ctx.Next() //调用下一级handler fmt.Println("AdminRouteMidware: after call next") } func main() { app := iris.New() // 注册中间件 app.Use(Middleware1) app.Use(Middleware2) // 注册默认的恢复中间件 app.Use(recover.New()) // 注册默认的日志中间件 app.Use(logger.New()) // 路由处理程序 app.Get("/", MyHandler) app.UseGlobal(GlobalMidware) apiadmin := app.Party("/admin") apiadmin.Use(AdminMidware1) apiadmin.UseRouter(AdminRouteMidware) apiadmin.Get("/hello", AdminHelloHandler) // 启动应用 app.Run(iris.Addr(":8080")) }
把程序跑起来之后,用浏览器访问一下 127.0.0.1:8080/admin/hello
可以看到程序有如下输出:
Iris Version: 12.2.0 Now listening on: http://localhost:8080 Application started. Press CTRL+C to shut down. AdminRouteMidware: before call next GlobalMidware: before call next Middleware 1: before call next Middleware 2: before call next AdminMidware: before call next AdminHelloHandler: Hello from handler AdminMidware: after call next [INFO] 2024/02/07 22:10 200 940.9µs 127.0.0.1 GET /admin/hello Middleware 2: after call next Middleware 1: after call next GlobalMidware: after call next AdminRouteMidware: after call next
从这个结果来观察所有handler执行的顺序,可以知道:
1.首先执行的是路由组的Handler,也就是apiadmin.UseRouter(AdminRouteMidware)注册的这个
2.然后执行的是GlobalMidware,在其它所有Midware之前
3.然后执行的是使用Use函数注册的Handler,它们都是同一类型,先注册的先执行
所以,顺序就是Middleware 1、Middleware 2、recover、Logger、AdminMiddleware、
其中recover仅在错误时执行,未体现出来
4.最后执行路由对应的处理函数
其实观察整个调用过程,就是一层一层调用下一个,这也就是ctx.Next()的作用,调用完之后再一层一层返回
了解了这个过程,就知道该如何正确地使用中间件了!