【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,否则影响并发量
把日志/认证放到中间件里 便于统一管理
核心逻辑不要放进中间件 中间件应专注"拦截"而非"业务逻辑"
相关推荐
西安栈上月明软件科技4 小时前
从 Linux 0.01 到 AI 开源:星图邻的开源实践
人工智能·自然语言处理·架构·开源·fastapi
troy1287 小时前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
StevenSurpass15 小时前
打印业务彻底解耦:FastPrintAgent 统一 JSON 模型 + FastReport 引擎的设计与落地
mqtt·http·中间件·打印·fastreport
avi911119 小时前
无厘头 -- 基于vue 公用状态机,已用于放置类篮球卡牌Game
中间件·vue·公用状态·文件间通信
刚子编程2 天前
Ubuntu 22.04 Docker 从零部署全栈项目实录:Next.js + FastAPI + PostgreSQL 一次跑通
fastapi·nextjs·docker部署·全栈开发·ubuntu22.04
2401_868534782 天前
网络安全法规
安全·中间件
CSharp精选营2 天前
Ubuntu 22.04 Docker 从零部署全栈项目实录:Next.js + FastAPI + PostgreSQL 一次跑通
fastapi·nextjs·docker部署·全栈开发·ubuntu22.04
JIngles1232 天前
用 Dart 通过 S3 API 操作 MinIO:文件上传与下载 Demo
中间件·minio·存储
花酒锄作田3 天前
FastAPI 使用 session 认证
python·fastapi
kyrie_sakura4 天前
python学习笔记14 -- FastAPI
笔记·python·学习·fastapi