中间件概念 #
一、中间件概述 #
中间件是处理HTTP请求的拦截器,可以在请求到达处理函数前后执行特定逻辑。
1.1 中间件作用 #
text
┌─────────────────────────────────────────────────────────┐
│ 中间件作用 │
├─────────────────────────────────────────────────────────┤
│ │
│ 请求前处理 │
│ ├── 日志记录 │
│ ├── 身份认证 │
│ ├── 权限验证 │
│ ├── 参数验证 │
│ └── 限流控制 │
│ │
│ 请求后处理 │
│ ├── 响应修改 │
│ ├── 错误处理 │
│ ├── 性能统计 │
│ └── 响应压缩 │
│ │
└─────────────────────────────────────────────────────────┘
1.2 中间件执行流程 #
text
请求 → 中间件1 → 中间件2 → 中间件3 → 处理函数 → 中间件3 → 中间件2 → 中间件1 → 响应
│ │ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼ ▼
前置处理 前置处理 前置处理 业务逻辑 后置处理 后置处理 后置处理
二、中间件类型 #
2.1 中间件函数签名 #
go
type MiddlewareFunc func(HandlerFunc) HandlerFunc
type HandlerFunc func(Context) error
2.2 中间件级别 #
| 级别 | 说明 | 注册方式 |
|---|---|---|
| 全局中间件 | 应用于所有路由 | e.Use() |
| 路由组中间件 | 应用于分组路由 | g.Use() |
| 路由级中间件 | 应用于单个路由 | e.GET(path, handler, middleware) |
2.3 全局中间件 #
go
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.CORS())
e.GET("/users", getUsers)
e.GET("/posts", getPosts)
2.4 路由组中间件 #
go
e := echo.New()
api := e.Group("/api")
api.Use(middleware.JWT([]byte("secret")))
api.GET("/users", getUsers)
api.GET("/posts", getPosts)
2.5 路由级中间件 #
go
e := echo.New()
e.GET("/admin", adminHandler, middleware.JWT([]byte("secret")))
三、中间件原理 #
3.1 洋葱模型 #
text
┌─────────────────┐
│ Middleware 1 │
│ ┌───────────┐ │
│ │Middleware2│ │
│ │ ┌─────┐ │ │
│ │ │ H │ │ │
│ │ │ a │ │ │
│ │ │ n │ │ │
│ │ │ d │ │ │
│ │ │ l │ │ │
│ │ │ e │ │ │
│ │ │ r │ │ │
│ │ └─────┘ │ │
│ └───────────┘ │
└─────────────────┘
请求 ──────────────────────────────────────────────────▶
响应 ◀──────────────────────────────────────────────────
3.2 中间件链 #
go
func middleware1(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
fmt.Println("Middleware 1 - Before")
err := next(c)
fmt.Println("Middleware 1 - After")
return err
}
}
func middleware2(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
fmt.Println("Middleware 2 - Before")
err := next(c)
fmt.Println("Middleware 2 - After")
return err
}
}
func handler(c echo.Context) error {
fmt.Println("Handler")
return c.String(http.StatusOK, "OK")
}
func main() {
e := echo.New()
e.Use(middleware1)
e.Use(middleware2)
e.GET("/", handler)
e.Start(":8080")
}
输出:
text
Middleware 1 - Before
Middleware 2 - Before
Handler
Middleware 2 - After
Middleware 1 - After
3.3 中断中间件链 #
go
func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
token := c.Request().Header.Get("Authorization")
if token == "" {
return echo.NewHTTPError(http.StatusUnauthorized, "请登录")
}
return next(c)
}
}
四、内置中间件 #
4.1 Logger - 日志记录 #
go
e.Use(middleware.Logger())
自定义配置:
go
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Format: "method=${method}, uri=${uri}, status=${status}\n",
}))
4.2 Recover - 错误恢复 #
go
e.Use(middleware.Recover())
自定义配置:
go
e.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{
DisablePrintStack: false,
LogLevel: 1,
}))
4.3 CORS - 跨域处理 #
go
e.Use(middleware.CORS())
自定义配置:
go
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"https://example.com", "https://api.example.com"},
AllowMethods: []string{echo.GET, echo.POST, echo.PUT, echo.DELETE},
AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAuthorization},
}))
4.4 Gzip - 响应压缩 #
go
e.Use(middleware.Gzip())
自定义配置:
go
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
Level: 5,
}))
4.5 RateLimiter - 请求限流 #
go
e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(20)))
4.6 BasicAuth - 基础认证 #
go
e.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
if username == "admin" && password == "secret" {
return true, nil
}
return false, nil
}))
4.7 JWT - JWT认证 #
go
e.Use(middleware.JWT([]byte("secret")))
4.8 RequestID - 请求ID #
go
e.Use(middleware.RequestID())
4.9 Secure - 安全头 #
go
e.Use(middleware.Secure())
4.10 Static - 静态文件 #
go
e.Use(middleware.Static("static"))
五、中间件配置 #
5.1 Skipper函数 #
跳过特定路由:
go
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Skipper: func(c echo.Context) bool {
return c.Path() == "/health"
},
}))
5.2 Before函数 #
请求前处理:
go
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Before: func(c echo.Context) {
c.Set("startTime", time.Now())
},
}))
六、中间件执行顺序 #
6.1 执行顺序规则 #
text
1. 全局中间件按注册顺序执行
2. 分组中间件在全局中间件之后执行
3. 路由中间件在分组中间件之后执行
6.2 示例说明 #
go
e := echo.New()
e.Use(middleware1) // 第1个执行
e.Use(middleware2) // 第2个执行
api := e.Group("/api")
api.Use(middleware3) // 第3个执行
api.GET("/users", handler, middleware4) // 第4个执行
执行顺序:
text
middleware1 → middleware2 → middleware3 → middleware4 → handler → middleware4 → middleware3 → middleware2 → middleware1
七、中间件数据传递 #
7.1 使用Context存储 #
go
func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
user := &User{ID: 1, Name: "张三"}
c.Set("user", user)
return next(c)
}
}
func handler(c echo.Context) error {
user := c.Get("user").(*User)
return c.JSON(http.StatusOK, user)
}
7.2 类型安全获取 #
go
func getUser(c echo.Context) *User {
if user, ok := c.Get("user").(*User); ok {
return user
}
return nil
}
八、中间件最佳实践 #
8.1 中间件顺序建议 #
go
e := echo.New()
e.Use(middleware.RequestID()) // 1. 请求ID
e.Use(middleware.Recover()) // 2. 错误恢复
e.Use(middleware.Logger()) // 3. 日志记录
e.Use(middleware.Gzip()) // 4. 响应压缩
e.Use(middleware.CORS()) // 5. 跨域处理
e.Use(middleware.RateLimiter()) // 6. 限流
e.Use(middleware.JWT()) // 7. 认证
8.2 中间件组织 #
go
func setupMiddleware(e *echo.Echo) {
e.Use(middleware.RequestID())
e.Use(middleware.Recover())
e.Use(middleware.Logger())
if config.EnableGzip {
e.Use(middleware.Gzip())
}
if config.EnableCORS {
e.Use(middleware.CORSWithConfig(config.CORSConfig))
}
}
8.3 环境区分 #
go
func setupMiddleware(e *echo.Echo, env string) {
e.Use(middleware.Recover())
if env == "development" {
e.Use(middleware.Logger())
}
if env == "production" {
e.Use(middleware.Gzip())
e.Use(middleware.Secure())
}
}
九、完整示例 #
go
package main
import (
"fmt"
"net/http"
"time"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.RequestID())
e.Use(middleware.Recover())
e.Use(middleware.Logger())
e.Use(middleware.Gzip())
e.Use(middleware.CORS())
e.Use(timingMiddleware)
e.GET("/", home)
e.GET("/health", health)
api := e.Group("/api")
api.Use(authMiddleware)
api.GET("/users", getUsers)
api.GET("/profile", getProfile)
e.Logger.Fatal(e.Start(":8080"))
}
func timingMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
start := time.Now()
err := next(c)
duration := time.Since(start)
c.Set("duration", duration)
fmt.Printf("Request took %v\n", duration)
return err
}
}
func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
token := c.Request().Header.Get("Authorization")
if token == "" {
return echo.NewHTTPError(http.StatusUnauthorized, "请登录")
}
c.Set("userID", "123")
return next(c)
}
}
func home(c echo.Context) error {
return c.String(http.StatusOK, "Welcome!")
}
func health(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{
"status": "healthy",
})
}
func getUsers(c echo.Context) error {
return c.JSON(http.StatusOK, []map[string]string{
{"id": "1", "name": "张三"},
{"id": "2", "name": "李四"},
})
}
func getProfile(c echo.Context) error {
userID := c.Get("userID").(string)
return c.JSON(http.StatusOK, map[string]string{
"userID": userID,
"name": "张三",
})
}
十、总结 #
中间件概念要点:
| 概念 | 说明 |
|---|---|
| 中间件函数 | func(HandlerFunc) HandlerFunc |
| 全局中间件 | e.Use() |
| 分组中间件 | g.Use() |
| 路由中间件 | e.GET(path, handler, middleware) |
| 洋葱模型 | 请求进入、响应返回 |
| 数据传递 | c.Set() / c.Get() |
准备好学习内置中间件了吗?让我们进入下一章!
最后更新:2026-03-28