【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,否则影响并发量
把日志/认证放到中间件里 便于统一管理
核心逻辑不要放进中间件 中间件应专注"拦截"而非"业务逻辑"
相关推荐
曲幽2 天前
FastAPI + SQLAlchemy 2.0 通用CRUD操作手册 —— 从同步到异步,一次讲透
python·fastapi·web·async·sqlalchemy·session·crud·sync·with
wytraining2 天前
快速入门 FastAPI 项目
jvm·oracle·fastapi
码界筑梦坊2 天前
94-基于Python的商品物流数据可视化分析系统
开发语言·python·mysql·信息可视化·数据分析·毕业设计·fastapi
zhz52142 天前
一个简单、轻量级且安全的离线GIS 系统架构设计
安全·系统架构·vue·gis·fastapi
爱吃烤鸡翅的酸菜鱼3 天前
Maven中BOM(Bill of Materials)的使用详解
java·中间件·maven·源代码管理
L-影3 天前
FastAPI全解析(下):除了快,它还能干多少脏活累活?
python·fastapi
码界筑梦坊3 天前
302-基于Python的安卓应用市场数据可视化分析推荐系统
开发语言·python·信息可视化·毕业设计·fastapi
MY_TEUCK3 天前
【MY_TRUCK中间件实战】Redis 入门教程:从基础命令到 Spring Boot 实战
spring boot·redis·中间件
ILYT NCTR3 天前
SocketTool、串口调试助手、MQTT中间件基础
单片机·嵌入式硬件·中间件
Ares-Wang3 天前
flask、flask-restful、fastAPI
flask·restful·fastapi