中间件(Middleware)是后端开发中的一个核心概念,它在请求(Request)和响应(Response)之间扮演着桥梁角色。以下是关于中间件的详细解释:
基本概念
中间件是在请求到达最终处理程序之前或响应返回客户端之前执行的一系列函数或组件。它可以:
访问请求对象(req)、响应对象(res)
执行任意代码
修改请求和响应对象
结束请求-响应周期
调用堆栈中的下一个中间件
中间件的工作原理
典型的中间件工作流程:
客户端请求 → 中间件1 → 中间件2 → ... → 路由处理 → 中间件N → ... → 中间件2 → 中间件1 → 客户端响应
以下用一个例子来说明
package main
import (
"github.com/gin-gonic/gin"
"log"
"time"
)
func main() {
r := gin.New()
// 中间件1:记录请求开始时间
r.Use(func(c *gin.Context) {
log.Println("中间件1 - 开始")
start := time.Now()
c.Set("startTime", start) // 在上下文中存储数据
// 模拟从Header获取用户信息
user := c.GetHeader("X-User")
if user != "" {
c.Set("user", user)
}
c.Next() // 移交控制权给下一个中间件/处理程序
latency := time.Since(start)
log.Printf("中间件1 - 结束, 耗时: %v", latency)
})
// 中间件2:认证检查
r.Use(func(c *gin.Context) {
log.Println("中间件2 - 认证检查")
if c.GetHeader("X-Token") != "my-secret-token" {
c.AbortWithStatusJSON(401, gin.H{"error": "认证失败"})
// 注意:这里没有调用c.Next(),请求处理被中断
return
}
c.Next()
})
// 路由处理
r.GET("/hello", func(c *gin.Context) {
log.Println("主处理函数 - 开始处理")
// 从上下文中获取中间件设置的数据
user, exists := c.Get("user")
if exists {
log.Printf("当前用户: %v", user)
}
time.Sleep(100 * time.Millisecond) // 模拟业务处理耗时
c.JSON(200, gin.H{"message": "Hello World"})
log.Println("主处理函数 - 处理完成")
})
r.Run(":8080")
}
处理流程如下:
1. 请求进入
- 中间件1开始执行,记录开始时间,设置user信息
- 调用 c.Next() 进入下一个中间件
2. 认证检查
- 中间件2检查token,验证通过
- 调用 c.Next() 进入路由处理函数
3. 主处理
- 路由函数执行业务逻辑
- 返回JSON响应
4. 反向回溯
- 返回到中间件2(但它没有 c.Next() 后的代码)
- 返回到中间件1,计算并记录耗时