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()的作用,调用完之后再一层一层返回

了解了这个过程,就知道该如何正确地使用中间件了!

posted @ 2024-02-07 22:30  黑月教主  阅读(59)  评论(0编辑  收藏  举报