【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,否则影响并发量
把日志/认证放到中间件里 便于统一管理
核心逻辑不要放进中间件 中间件应专注"拦截"而非"业务逻辑"
相关推荐
喜欢的名字被抢了6 小时前
FastAPI 接口安全与工程化 JWT、测试和配置管理
安全·fastapi
Maiko Star1 天前
从零落地「AI掘金头条」新闻模块:FastAPI + SQLAlchemy 异步实战
python·fastapi
喜欢的名字被抢了1 天前
FastAPI 接入异步 PostgreSQL 完成任务 CRUD 与数据库迁移
数据库·postgresql·fastapi
Esaka_Forever1 天前
uvicorn main.py 命令说明
fastapi
巴啦啦小魔仙变身2 天前
FastAPI 01 Create Demo
python·fastapi
李昊哲小课4 天前
fastapi sse websocket 奶茶店实时订单看板
人工智能·python·websocket·网络协议·fastapi·sse
李昊哲小课4 天前
fastapi sse websocket 智能家居实时控制台
python·websocket·智能家居·fastapi·sse
赵广陆4 天前
SQLAlchemy ORM 超全教程
python·fastapi
ThsPool4 天前
【ENVI二次开发学习整理 02】IDL语言基础与程序设计
学习·中间件
程序员良辰4 天前
【TongWeb7】启动接近两分钟问题排查
java·开发语言·中间件