【FastAPI】 依赖注入 + 中间件详解

FastAPI 依赖注入 + 中间件详解(完整技术文档)

本文基于你提供的代码与注释,系统化、结构化、深入原理地讲解 FastAPI 的两个核心机制:依赖注入 & 中间件


一、依赖注入系统:让代码更具复用性

核心思想: 将"通用功能"抽象为"可重用的组件",由 FastAPI 自动注入到路径操作函数中。


什么是依赖注入?

  • 定义 :依赖注入(Dependency Injection, DI)是一种设计模式,用于将对象的依赖关系外部化,由框架(如 FastAPI)在运行时自动提供。
  • 好处
    • 避免代码重复
    • 提高模块化与可维护性
    • 易于测试、扩展与复用

举例:分页参数 skiplimit 在多个接口中都用到,可以用依赖项统一管理。


依赖注入的三大步骤

步骤 操作 说明
1. 创建依赖项 定义函数或类 实现公共逻辑(如分页、认证、数据库会话)
2. 导入 Depends from fastapi import Depends 启用依赖注射系统
3. 声明依赖项 使用 Depends(函数名) 注入到路径操作函数参数中

实战:分页参数依赖项(通用逻辑复用)

python 复制代码
from fastapi import Depends, FastAPI, Query

#  1. 创建依赖项:提取通用逻辑
async def common_parameters(
    skip: int = Query(0, ge=0, description="跳过多少条"),
    limit: int = Query(10, le=100, description="返回条数上限")
):
    return {"skip": skip, "limit": limit}

app = FastAPI()

#  3. 声明依赖项:在路径操作函数中使用
@app.get("/news/news_list")
async def get_news_list(commons: dict = Depends(common_parameters)):
    return commons

@app.get("/users/users_list")
async def get_users_list(commons: dict = Depends(common_parameters)):
    return commons

@app.get("/products/product_list")
async def get_product_list(commons: dict = Depends(common_parameters)):
    return commons

客户端请求示例:

复制代码
GET /news/news_list?skip=20&limit=5

返回结果:

json 复制代码
{"skip": 20, "limit": 5}

执行流程图(必看)

复制代码
客户端请求 → FastAPI 路由匹配 → 检测到 Depends(common_parameters)
         ↓
调用 common_parameters(skip=20, limit=5) → 返回字典
         ↓
注入到 commons 参数
         ↓
执行 get_news_list() → 返回数据
         ↓
响应返回客户端

依赖注入的本质:自动注入 + 类型推断

  • FastAPI 会自动根据函数参数的 类型注解 来决定如何注入。
  • 例如:request: Requestdb: AsyncSessioncommons: dict,框架会自动填入对应对象。
  • 双向一体化:参数定义 + 类型提示 = 自动注入

重要提醒

  • 依赖项必须是 可调用对象 (函数或类 __call__ 方法)
  • 依赖项可以是 异步函数async def
  • 依赖项可以返回任意类型(dict、model、session 等)

最佳实践建议

建议 说明
使用 Query() 设置校验规则 ge=0le=100 防止非法参数
使用 description 提供 API 文档说明 自动生成 Swagger 文档,提升可读性
优先使用 Pydantic 模型作为依赖项 更安全、更结构化(如 BookCreate
依赖项应无副作用 不应修改全局状态或执行耗时操作
支持缓存的依赖项 sessioncacheauth_user,可声明为全局依赖

二、中间件(Middleware):全局拦截器

核心思想: 在请求进入路由前、响应返回客户端前,插入预处理与后处理逻辑。


中间件的作用

作用 说明
日志记录 记录请求 URL、IP、耗时
身份认证 检查 Token 是否有效
请求/响应过滤 改写 Header、Body、状态码
错误处理 捕获异常,返回统一错误码
性能分析 统计 API 响应时间
缓存控制 检查是否可缓存,返回缓存数据

中间件的调用机制

复制代码
客户端 → 中间件1(请求) → 中间件2(请求) → 路由函数 → 中间件2(响应) → 中间件1(响应) → 客户端

执行顺序:从上往下进入 → 从下往上返回


实战:定义两个中间件

python 复制代码
from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware("http")
async def middleware1(request: Request, call_next):
    print("🔧 请求进入中间件1:开始")  # 执行前
    response = await call_next(request)  # 调用下一个处理
    print("🔧 响应进入中间件1:结束")
    return response

@app.middleware("http")
async def middleware2(request: Request, call_next):
    print("🔧 请求进入中间件2:开始")
    response = await call_next(request)
    print("🔧 响应进入中间件2:结束")
    return response

@app.get("/")
async def root():
    return {"message": "Hello World"}

访问 http://localhost:8000

控制台输出:

复制代码
🔧 请求进入中间件1:开始
🔧 请求进入中间件2:开始
🔧 响应进入中间件2:结束
🔧 响应进入中间件1:结束

执行顺序:1 → 2 → 路由 → 2 → 1


关键术语解释

术语 说明
request: Request FastAPI 的请求对象,包含 headers、path、cookies 等信息
call_next(request) 继续执行下一个中间件或路由函数
response call_next 返回的响应对象,可被修改后返回

中间件的最佳实践

建议 说明
使用 async def 定义中间件 因为 FastAPI 是异步框架
优先使用 await call_next(request) 否则不会进入路由
避免阻塞操作 如同步 I/O,否则影响并发量
把日志/认证放到中间件里 便于统一管理
核心逻辑不要放进中间件 中间件应专注"拦截"而非"业务逻辑"
相关推荐
heimeiyingwang14 小时前
【架构实战】海量数据存储:分库分表中间件实战
中间件·架构
敢敢のwings15 小时前
ROS2通信中间件深度解析:从DDS到下一代传输架构整理
中间件·架构
理人综艺好会16 小时前
路由中间件快速了解(Gin版)
中间件·gin
别抢我的锅包肉16 小时前
【 FastAPI 】ORM
fastapi
别抢我的锅包肉1 天前
【FastAPI】 响应类型详解:从默认 JSON 到自定义响应
python·fastapi
lifewange2 天前
MQ中间件是什么
中间件
小邓的技术笔记2 天前
聊聊 ASP.NET Core 中间件和过滤器的区别
后端·中间件·asp.net
龙腾AI白云2 天前
大模型Prompt实战:精准生成专业技术文档
plotly·pyqt·fastapi·tornado·dash
8Qi83 天前
微服务通信:同步 vs 异步与MQ选型指南
java·分布式·微服务·云原生·中间件·架构·rabbitmq