全局中间件与路由组中间件
中间件可以全局注册,也可以限定在特定路由组,灵活控制请求处理范围。
全局中间件
使用 r.Use() 注册,作用于所有路由:
Go
func main() {
r := gin.New()
// 全局注册
r.Use(loggerMiddleware())
r.Use(corsMiddleware())
// 所有路由都会经过这些中间件
r.GET("/api/users", listUsers)
r.GET("/api/products", listProducts)
r.GET("/health", healthCheck) // 也经过全局中间件
r.Run(":8080")
}
路由组中间件
使用 group.Use() 注册,仅作用于组内路由:
Go
func main() {
r := gin.New()
// 全局中间件
r.Use(loggerMiddleware())
// 需认证的 API 组
authGroup := r.Group("/api")
authGroup.Use(authMiddleware())
{
authGroup.GET("/users", listUsers)
authGroup.GET("/profile", getProfile)
}
// 公开 API,不需要认证
publicGroup := r.Group("/public")
// 不添加认证中间件
{
publicGroup.GET("/info", getInfo)
publicGroup.GET("/health", healthCheck)
}
r.Run(":8080")
}
单路由中间件
直接在路由注册时添加:
Go
func main() {
r := gin.New()
// 单路由添加中间件
r.GET("/admin", authMiddleware(), roleMiddleware("admin"), adminHandler)
// 多个中间件按顺序执行
r.DELETE("/user/:id",
authMiddleware(),
permissionMiddleware("delete_user"),
deleteUserHandler,
)
r.Run(":8080")
}
中间件执行顺序
Go
func main() {
r := gin.New()
// 全局中间件
r.Use(middlewareA())
r.Use(middlewareB())
// 路由组中间件
api := r.Group("/api")
api.Use(middlewareC())
api.Use(middlewareD())
api.GET("/test", middlewareE(), handler)
// 执行顺序:A → B → C → D → E → Handler → E → D → C → B → A
}
嵌套路由组
Go
func main() {
r := gin.New()
r.Use(loggerMiddleware())
api := r.Group("/api")
api.Use(authMiddleware())
// 嵌套子组
admin := api.Group("/admin")
admin.Use(roleMiddleware("admin"))
{
admin.GET("/users", listAdminUsers)
admin.DELETE("/user/:id", deleteUser)
}
// 普通用户组
user := api.Group("/user")
{
user.GET("/profile", getProfile)
}
// 执行顺序:
// /api/admin/users: logger → auth → role → handler
// /api/user/profile: logger → auth → handler
}
中间件适用范围对比
| 注册方式 | 适用范围 | 方法 |
|---|---|---|
| 全局中间件 | 所有路由 | r.Use() |
| 路由组中间件 | 组内所有路由 | group.Use() |
| 单路由中间件 | 单个路由 | 路义时添加 |
排除特定路由
Go
func skipAuthMiddleware() gin.HandlerFunc {
skipPaths := []string{"/health", "/metrics", "/login"}
return func(c *gin.Context) {
path := c.Request.URL.Path
for _, skip := range skipPaths {
if path == skip {
c.Next()
return
}
}
// 其他路径检查认证
if !isAuthenticated(c) {
c.AbortWithStatus(401)
return
}
c.Next()
}
}
最佳实践配置
Go
func main() {
r := gin.New()
// 1. 全局基础中间件
r.Use(gin.Recovery())
r.Use(loggerMiddleware())
r.Use(corsMiddleware())
// 2. 公开路由
r.GET("/health", healthCheck)
r.GET("/metrics", metricsHandler)
r.POST("/login", loginHandler)
// 3. 需认证的 API
api := r.Group("/api/v1")
api.Use(authMiddleware())
{
api.GET("/users", listUsers)
api.GET("/profile", getProfile)
}
// 4. 管理员 API
admin := api.Group("/admin")
admin.Use(roleMiddleware("admin"))
{
admin.DELETE("/users/:id", deleteUser)
admin.POST("/config", updateConfig)
}
r.Run(":8080")
}
执行流程图
text
请求
↓
全局中间件 (r.Use)
↓
路由组中间件 (group.Use)
↓
路由中间件 (路由注册时)
↓
处理函数
↓
逆向返回
全局中间件放基础功能,认证等业务中间件放路由组。
要点总结
r.Use()注册全局中间件,作用于所有路由group.Use()注册路由组中间件,仅作用于组内路由- 单路由可直接在路由注册时添加中间件
- 中间件按注册顺序执行,形成洋葱结构
- 合理分组可避免不必要的中间件执行
📝 发现内容有误?点击此处直接编辑