BeforeActivation中注册中间件必须用b.Router().Use()而非b.Use(),因b无Use方法;b.Router().Use()作用于控制器全部路由,b.Handle()传参中间件仅作用于单个handler,且局部中间件总在全局之后执行。

BeforeActivation 里注册中间件必须用 b.Router().Use(),不是 b.Use()
很多人在 BeforeActivation 方法里直接调 b.Use(middleware),结果中间件根本没生效。这是因为 b 是 mvc.BeforeActivation 实例,它没有 Use 方法 —— 真正挂载中间件的地方是它内部的路由实例:b.Router()。
正确写法是:
func (c *MyController) BeforeActivation(b mvc.BeforeActivation) {
b.Router().Use(authMiddleware, loggingMiddleware)
b.Handle("GET", "/profile", "GetProfile")
}
-
b.Router().Use()才会把中间件注入到该控制器对应的所有路由上 -
b.Handle()后注册的中间件只对当前这一个 handler 生效(可传参追加) - 如果同时用了
b.Router().Use()和b.Handle(..., middleware),后者会 prepend 到前者之前执行
同一个控制器内不同 handler 的中间件要隔离?用 b.Handle() 单独传参
比如 GetProfile 需要 JWT 鉴权,但 GetPublicInfo 不需要,就不能全局挂 b.Router().Use(),否则所有方法都被套上。
这时应该为每个 b.Handle() 显式传入中间件切片:
func (c *MyController) BeforeActivation(b mvc.BeforeActivation) {
b.Handle("GET", "/profile", "GetProfile", authMiddleware)
b.Handle("GET", "/info", "GetPublicInfo") // 没传中间件,裸奔
}
- 传入的中间件只作用于该条路由,和其他 handler 完全无关
- 顺序很重要:传入
[]iris.Handler{a, b},a先执行,b后执行 - 别漏掉
ctx.Next()—— 如果你在中间件里写了响应但忘了ctx.StopExecution(),后续 handler 仍会执行
AfterActivation 适合做运行时中间件注入,比如按路由名动态加缓存
AfterActivation 在控制器注册完成、路由已生成但尚未启动监听时触发,适合做“查路由+改中间件”的操作。典型场景是给某个特定路径加缓存,又不想污染其他 handler。
示例:给 /v2/products 加 cacheHandler,但不碰 /v2/orders
func (c *ProductController) AfterActivation(a mvc.AfterActivation) {
r := a.GetRoute("GetProducts")
if r != nil {
r.Handlers = append([]iris.Handler{cacheHandler}, r.Handlers...)
}
}
-
a.GetRoute("MethodName")返回的是*mvc.Route,可直接修改其Handlers字段 - 用
append(..., r.Handlers...)是前置插入,确保缓存中间件最先执行 - 注意判空:
r可能为nil(比如方法名拼错或没被b.Handle()绑定)
局部中间件和全局中间件的执行顺序:局部永远在全局之后
Iris 的中间件执行链是「全局 → 路由组 → 局部」三层嵌套。哪怕你在 BeforeActivation 里用 b.Router().Use() 注册了中间件,它也一定在 app.Use() 或 app.Party("/v2").Use() 之后执行。
- 也就是说,全局日志中间件会先打日志,然后才进你控制器里的鉴权中间件
- 如果你想让某个控制器的中间件「早于」全局中间件(比如提前拒绝非法 Host),只能把它挂到更外层的
Party上,不能塞进控制器 - 调试时可以用
ctx.Application().Logger().Infof("in %s", ctx.Path())打点确认执行顺序
最易忽略的一点:局部中间件的生命周期只绑定到该控制器注册的路由上,不会影响同路径下其他 Party 或普通 app.Get() 注册的 handler —— 它们压根不在同一个路由树分支里。


















