【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,否则影响并发量
把日志/认证放到中间件里 便于统一管理
核心逻辑不要放进中间件 中间件应专注"拦截"而非"业务逻辑"
相关推荐
java1234_小锋2 小时前
FastAPI python web开发- 集成SQLAlchemy ORM 操作数据库
fastapi
不瘦80斤不改名14 小时前
全家桶、乐高积木与类型引擎:重新认识 Django、Flask 与 FastAPI
django·flask·fastapi
fuquxiaoguang1 天前
中间件的“价值重估”:传统同质化竞争终结,AI智能编排时代开启
人工智能·中间件
Exclusive_Cat2 天前
FastAPI热重载失效?降级uvicorn解决
python·fastapi
fuquxiaoguang2 天前
中间件的“结构性升级”:当智能编排成为政企采购的“硬指标”
中间件·ai智能体·ai原生
C137的本贾尼2 天前
第七篇:消息队列(MQ)——就是个带存储的异步通信管道
java·开发语言·中间件
初学AI的小高2 天前
FastAPI 工程实践:LLM 应用的 API 设计之道
后端·fastapi
java1234_小锋2 天前
FastAPI python web开发- 中间件
fastapi
半夜修仙3 天前
RabbitMQ的推模式和拉模式
java·分布式·中间件·rabbitmq·github·java-rabbitmq
不能只会打代码3 天前
Day 002 — Python 工程化 & FastAPI & 数据库速通
数据库·redis·python·docker·fastapi·测试