FastAPI进阶开发:中间件、依赖注入

目录

一、中间件:统一处理所有请求的利器

1.1、中间件的核心应用场景

1.2、中间件的定义与基本使用

1.3、多个中间件的执行顺序

1.4、中间件的核心特点

二、依赖注入:抽离通用逻辑,实现代码复用

2.1、依赖注入的核心概念

2.2、依赖注入的实战使用

[步骤 1:创建依赖项(通用逻辑函数)](#步骤 1:创建依赖项(通用逻辑函数))

[步骤 2:导入 Depends,在路由中声明依赖](#步骤 2:导入 Depends,在路由中声明依赖)

完整代码

三、中间件与依赖注入的核心区别


FastAPI 作为高性能的异步 Web 框架,凭借简洁的语法、自动的接口文档和优秀的性能,成为 Python Web 开发的热门选择。入门之后,想要开发企业级的 Web 应用,还需要掌握中间件、依赖注入和ORM三大核心进阶特性 ------ 它们能帮我们实现代码复用、逻辑解耦,让数据库操作更优雅,大幅提升项目的可维护性和扩展性。

一、中间件:统一处理所有请求的利器

在 FastAPI 中,中间件(Middleware)是一个在每次请求进入应用和响应返回客户端前都会执行的函数,相当于所有请求的 "统一入口和出口",适合实现全局化的处理逻辑。

1.1、中间件的核心应用场景

中间件的设计初衷是为所有接口添加通用处理逻辑,无需在每个路由中重复编写。

典型场景包括:

  • 全局用户身份认证、权限校验
  • 接口请求 / 响应日志记录、性能监控
  • 跨域请求处理(CORS)、统一设置响应头
  • 全局异常捕获与处理

1.2、中间件的定义与基本使用

定义中间件需使用**@app.middleware("http")** 装饰器,函数为异步类型,接收request(请求对象)和call_next(调用下一个中间件 / 路由处理函数的方法)两个参数,最终返回响应对象。

python 复制代码
from fastapi import FastAPI

app = FastAPI()

# 定义基础中间件
@app.middleware("http")
# async:异步处理,协程
async def global_middleware(request, call_next):
    # request:请求,cell_next:下一个中间件或路由处理函数
    # 请求到达路由前执行:start部分
    print(f"中间件开始处理:{request.method} {request.url}")
    # 传递请求到下一个中间件/路由
    response = await call_next(request)
    # 响应返回客户端前执行:end部分
    print(f"中间件处理完成:响应状态码 {response.status_code}")
    return response

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

1.3、多个中间件的执行顺序

FastAPI 中注册多个中间件时,start 部分按注册逆序执行,end 部分按注册顺序执行(自下而上执行 start,自上而下执行 end),可以理解为 "洋葱模型"------ 请求从外层穿透到内层路由,响应从内层穿透回外层客户端。

python 复制代码
from  fastapi import FastAPI

app = FastAPI()


# 中间件2
@app.middleware("http")
async def middleware2(request, call_next):
    print("middleware2 start")  # 第一步执行:打印这行
    # 第二步执行:调用 call_next(request)
    # 此时 call_next 的作用是:把请求传递给下一个中间件(middleware1)
    response = await call_next(request)
    print("middleware2 end")  # 第六步执行:打印这行
    return response  # 第七步:返回最终的响应

# 中间件1
@app.middleware("http")
async def middleware1(request, call_next):
    print("middleware1 start")  # 第三步执行:打印这行
    # 第四步执行:调用 call_next(request)
    # 此时 call_next 的作用是:把请求传递给最终的路由处理函数(比如你的 / 接口)
    response = await call_next(request)
    print("middleware1 end")  # 第五步执行:打印这行
    return response  # 把路由返回的 response 传回 middleware2

# 访问这个根路由
@app.get("/")
async def root():
    print("路由函数执行")  # 第四步中间执行:打印这行
    return {"message": "Hello FastAPI"}  # 返回响应

# 访问/时,控制台输出顺序:
# middleware2 start  →  middleware1 start  →  路由函数执行  →  middleware1 end  →  middleware2 end

1.4、中间件的核心特点

  • **全局生效:**控制所有请求和响应,无需手动调用
  • **异步执行:**基于协程,不阻塞主线程,符合 FastAPI 的异步设计
  • **责任单一:**一个中间件实现一个通用逻辑,便于维护

二、依赖注入:抽离通用逻辑,实现代码复用

如果说中间件是 "全局无差别处理",那么依赖注入就是精细化的通用逻辑复用------ 可以自定义哪些路由使用通用逻辑,完美解决多个接口重复编写相同代码的问题(如分页参数、数据库连接、局部权限校验)。

2.1、依赖注入的核心概念

  • **依赖项:**可重用的组件(函数 / 类),负责提供某种功能或数据(如分页参数解析、数据库会话创建)
  • **注入:**FastAPI 自动调用依赖项,并将执行结果传递到路由处理函数中,无需手动调用
  • **核心优势:**代码复用、逻辑解耦、易于测试(可轻松替换模拟依赖,无需修改业务代码)

依赖注入的典型应用场景:

  • 抽取多个路由的通用参数(如分页的skip/limit、排序参数)
  • 共享数据库连接 / 会话管理(创建、使用、关闭)
  • 局部接口的身份认证、权限检查(非全局)
  • 从请求中提取和验证自定义参数(路径、查询、请求体)

2.2、依赖注入的实战使用

分页参数复用为例,这是开发中最常见的场景,多个接口都需要skip(跳过条数)和limit(返回条数)参数,通过依赖注入可一次性实现,多处调用。

步骤 1:创建依赖项(通用逻辑函数)

python 复制代码
from fastapi import Query
# 分页参数逻辑共用:新闻列表和用户列表
# 1.依赖项
# 定义分页参数依赖项
async def common_page_parameters(
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(10, le=100, description="返回的记录数,最大100")
):
    return {"skip": skip, "limit": limit}

步骤 2:导入 Depends,在路由中声明依赖

python 复制代码
from fastapi import FastAPI, Depends #2.导入Depends

app = FastAPI()

# 新闻列表接口:使用分页依赖
@app.get("/news/list")
async def get_news_list(commons = Depends(common_page_parameters)):
    # 直接使用依赖项返回的分页参数
    return {"message": "新闻列表", **commons}

# 用户列表接口:复用同一个分页依赖
@app.get("/users/list")
async def get_user_list(commons = Depends(common_page_parameters)):
    return {"message": "用户列表", **commons}

完整代码

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

app = FastAPI()

# 定义分页参数依赖项
async def common_page_parameters(
    skip: int = Query(0, ge=0, description="跳过的记录数"),
    limit: int = Query(10, le=100, description="返回的记录数,最大100")
):
    return {"skip": skip, "limit": limit}

# 新闻列表接口:使用分页依赖
@app.get("/news/list")
async def get_news_list(commons = Depends(common_page_parameters)):
    # 直接使用依赖项返回的分页参数
    return {"message": "新闻列表", **commons}

# 用户列表接口:复用同一个分页依赖
@app.get("/users/list")
async def get_user_list(commons = Depends(common_page_parameters)):
    return {"message": "用户列表", **commons}

三、中间件与依赖注入的核心区别

很多开发者会混淆两者的使用场景,核心区别在于作用范围和灵活性

| 特性 | 中间件 | 依赖注入 |
| 作用范围 | 控制所有请求 | 控制自定义路由 |
| 调用方式 | 自动全局生效,无需声明 | 路由中通过 Depends 声明 |
| 灵活性 | 低(全局统一) | 高(精细化控制) |

适用场景 全局通用逻辑 局部通用逻辑

简单来说:所有接口都需要的逻辑用中间件,部分接口需要的逻辑用依赖注入

相关推荐
曲幽10 小时前
FastAPI + PostgreSQL 实战:给应用装上“缓存”和“日志”翅膀
redis·python·elasticsearch·postgresql·logging·fastapi·web·es·fastapi-cache
曲幽1 天前
FastAPI + PostgreSQL 实战:从入门到不踩坑,一次讲透
python·sql·postgresql·fastapi·web·postgres·db·asyncpg
曲幽2 天前
数据库实战:FastAPI + SQLAlchemy 2.0 + Alembic 从零搭建,踩坑实录
python·fastapi·web·sqlalchemy·db·asyncio·alembic
曲幽6 天前
FastAPI流式输出实战与避坑指南:让AI像人一样“边想边说”
python·ai·fastapi·web·stream·chat·async·generator·ollama
曲幽8 天前
不止于JWT:用FastAPI的Depends实现细粒度权限控制
python·fastapi·web·jwt·rbac·permission·depends·abac
曲幽9 天前
FastAPI分布式系统实战:拆解分布式系统中常见问题及解决方案
redis·python·fastapi·web·httpx·lock·asyncio
曲幽9 天前
FastAPI压力测试实战:Locust模拟真实用户并发及优化建议
python·fastapi·web·locust·asyncio·test·uvicorn·workers
曲幽10 天前
FastAPI实战:打造本地文生图接口,ollama+diffusers让AI绘画更听话
python·fastapi·web·cors·diffusers·lcm·ollama·dreamshaper8·txt2img
曲幽11 天前
我用FastAPI接ollama大模型,差点被asyncio整崩溃(附对话窗口实战)
python·fastapi·web·async·httpx·asyncio·ollama