FastAPI 系列 · 第 1 篇:初体验------从 Spring Boot 工程师视角认识 FastAPI
适合人群 :熟悉 Java Spring Boot、希望上手 Python 后端开发的工程师
阅读时间 :约 25 分钟
一句话定位 :FastAPI 是 Python 后端生态中兼顾高性能与开发效率的现代框架,本篇带你从零搭建shop-api骨架,建立与 Spring Boot 的全景映射认知。
一、为什么是 FastAPI?
Python 后端框架百花齐放,Flask、Django、FastAPI 三分天下。对 Java 工程师而言,选择一个框架不只是选语法,更是选择一套工程思维。理解它们的设计哲学,才能在正确的场景做正确的技术决策。
1.1 Python 后端框架横向对比
| 维度 | Flask | Django | FastAPI |
|---|---|---|---|
| 定位 | 微框架,极简内核 | 全栈框架,"自带电池" | 现代异步框架,性能优先 |
| 路由方式 | 装饰器 | URLconf(集中式) | 装饰器 |
| 异步支持 | 有限(需扩展) | Django 3.1+ 支持 | 原生 async/await |
| 数据校验 | 无内置,依赖扩展 | Form/Serializer | Pydantic(编译级校验) |
| 自动文档 | 无内置 | 无内置 | OpenAPI + ReDoc 开箱即用 |
| ORM 绑定 | 无内置 | 强绑定 Django ORM | 无绑定,推荐 SQLModel/SQLAlchemy |
| 性能(ASGI) | WSGI,性能一般 | WSGI(可选 ASGI) | ASGI,接近 Node.js |
| 学习曲线 | 低 | 中高 | 中 |
| Spring Boot 类比 | Spring MVC 裸用 | Spring Boot(全家桶) | Spring WebFlux(响应式) |
💡 选型建议:新建微服务、API 网关、ML 推理服务首选 FastAPI;需要管理后台、CMS 场景可考虑 Django;快速原型可用 Flask。
1.2 FastAPI 的核心优势
FastAPI 于 2018 年由 Sebastián Ramírez 发布,短短数年跻身 GitHub Star 最多的 Python 框架之列。其核心优势来自三个设计决策:
1. 性能:底层基于 Starlette(ASGI 框架),充分利用 Python 的 asyncio 事件循环,在 I/O 密集型场景下吞吐量接近 Node.js 和 Go。
2. 类型安全:与 Python 类型注解深度整合,借助 Pydantic 在运行时执行数据校验,把"运行时报错"前移为"写代码时报错"。这一点与 Java 的编译期类型检查理念高度一致。
3. 自动文档:路由声明即文档,无需额外维护 Swagger YAML。这在 Spring Boot 中需要引入 springdoc-openapi 才能实现。
🤔 一个类比:如果说 Flask 是"空白画布",Django 是"精装修套房",那么 FastAPI 就是"带开放式厨房的 loft"------结构清晰,工具齐全,但不替你做决定。
二、核心架构
理解 FastAPI 的分层架构,是写出可维护代码的前提。FastAPI 并非从零实现 HTTP 服务器,而是在成熟的底层组件之上进行了精心的封装与整合。
2.1 三层架构关系
Uvicorn
(ASGI Server)
对应 Tomcat / Jetty
Starlette
(ASGI Framework)
对应 Spring MVC DispatcherServlet
FastAPI
(Application Layer)
对应 Spring MVC + Auto-configuration
Your Code
(Routes / Services / Models)
对应 @Controller / @Service / @Entity
各层职责说明:
| 层次 | 组件 | 职责 | Spring Boot 对应 |
|---|---|---|---|
| 传输层 | Uvicorn | 监听端口、处理 TCP 连接、实现 ASGI 协议 | Tomcat / Jetty(内嵌容器) |
| 框架层 | Starlette | 请求路由、中间件、WebSocket、静态文件 | Spring MVC(DispatcherServlet) |
| 应用层 | FastAPI | 依赖注入、参数解析、数据校验、OpenAPI 文档生成 | Spring Boot Auto-configuration |
| 业务层 | 用户代码 | Router、Service、Model 等业务逻辑 | @Controller、@Service、@Entity |
2.2 请求生命周期
一条 HTTP 请求的完整处理流程如下:
Route Handler Dependency Injection Router Middleware Stack Uvicorn (ASGI Server) Client Route Handler Dependency Injection Router Middleware Stack Uvicorn (ASGI Server) Client HTTP Request ASGI scope/receive/send 通过中间件链 匹配路由,解析路径/查询参数 注入依赖(DB Session、Auth 等) 返回 Response 对象 Pydantic 序列化校验 JSON Response 通过中间件链(响应处理) HTTP Response
📝 ASGI 说明:ASGI(Asynchronous Server Gateway Interface)是 WSGI 的异步升级版,定义了异步 Python Web 服务器与 Web 框架之间的标准接口。可类比 Java 的 Servlet 规范------Tomcat 实现了 Servlet 规范,Uvicorn 实现了 ASGI 规范。
2.3 Pydantic 的角色
Pydantic 是 FastAPI 生态中负责数据校验和序列化的核心库。其工作原理类似于 Spring Boot 中 @Valid + @RequestBody 的组合,但更彻底:
- 定义
BaseModel子类 → 声明字段类型和约束(类比 DTO + Bean Validation 注解) - FastAPI 自动将请求 JSON 反序列化为 Pydantic 模型(类比 Jackson + @RequestBody)
- 校验失败自动返回 422 Unprocessable Entity(类比 Spring 的 MethodArgumentNotValidException)
三、Spring Boot vs FastAPI 全景对比
对有 Spring Boot 背景的工程师来说,建立两个框架之间的"心智映射"是快速上手的捷径。
| 维度 | Spring Boot | FastAPI | 说明 |
|---|---|---|---|
| 启动入口 | @SpringBootApplication + main() |
app = FastAPI() + uvicorn.run() |
FastAPI 无注解式启动入口,直接实例化 |
| 路由声明 | @GetMapping("/path") |
@app.get("/path") |
语法更简洁,装饰器即路由 |
| 依赖注入 | @Autowired、@Bean、IoC 容器 |
Depends(func) 函数式 DI |
FastAPI DI 基于函数,无容器概念 |
| 配置文件 | application.yml / application.properties |
.env + pydantic-settings |
均支持多环境覆盖 |
| 请求体校验 | @Valid + @RequestBody DTO |
Pydantic BaseModel + 类型注解 |
原理相似,FastAPI 更简洁 |
| ORM 推荐 | Spring Data JPA(Hibernate) | SQLAlchemy 2.x / SQLModel | SQLModel 由 FastAPI 作者维护 |
| 安全框架 | Spring Security | FastAPI + python-jose / authlib | FastAPI 无内置安全框架,需手动集成 |
| 自动文档 | springdoc-openapi(需引入) | 内置 Swagger UI + ReDoc | FastAPI 开箱即用,无需额外配置 |
| 部署方式 | Fat JAR / Docker / k8s | Uvicorn + Gunicorn / Docker / k8s | 部署思路相似,均推荐容器化 |
| 异步模型 | WebFlux(Project Reactor) | asyncio + async/await | FastAPI 异步模型更接近 Node.js |
| 中间件 | Filter / HandlerInterceptor | Starlette Middleware | 均支持请求前后拦截 |
| 测试 | MockMvc / @SpringBootTest | TestClient(requests-like)/ pytest | FastAPI TestClient 用法类似 MockMvc |
⚠️ 重要差异:Spring Boot 有成熟的 IoC 容器,Bean 生命周期由容器管理;FastAPI 的 DI 是轻量级函数式设计,没有容器概念。这对设计单例服务(如数据库连接池)有重要影响,后续篇章会详细讨论。
四、环境搭建
4.1 Python 版本要求
FastAPI 要求 Python 3.8+,推荐使用 Python 3.11 或 3.12 以获得最佳性能和类型提示支持。
bash
# 检查 Python 版本
python3 --version
# 推荐:Python 3.11.x 或 3.12.x
4.2 创建虚拟环境
Python 的 venv(Virtual Environment)类比 Maven 的本地仓库隔离机制------每个项目拥有独立的依赖空间,互不干扰。
bash
# 创建项目目录(类比 mvn archetype:generate)
mkdir shop-api && cd shop-api
# 创建虚拟环境(.venv 是约定俗成的目录名)
python3 -m venv .venv
# 激活虚拟环境
# macOS / Linux:
source .venv/bin/activate
# Windows (PowerShell):
# .venv\Scripts\Activate.ps1
# 确认激活成功(路径前缀出现 (.venv))
which python
# 输出类似:/path/to/shop-api/.venv/bin/python
💡 类比说明 :venv 类似于 Maven 的 <localRepository> 配置,但粒度更细------每个项目独享一套 Python 解释器和依赖库,彻底避免"依赖地狱"。
4.3 安装依赖
bash
# 安装核心依赖(第 01 篇只需基础包)
pip install fastapi==0.111.0 uvicorn[standard]==0.29.0 python-dotenv==1.0.1 pydantic==2.7.1 pydantic-settings==2.2.1
# 冻结依赖版本到 requirements.txt(类比 pom.xml 锁定依赖版本)
pip freeze > requirements.txt
requirements.txt 内容(手动维护版,更清晰):
text
# FastAPI 核心
fastapi==0.111.0
# ASGI 服务器([standard] 包含 websockets、httptools 等性能扩展)
uvicorn[standard]==0.29.0
# 环境变量管理(类比 Spring 的 @Value + @ConfigurationProperties)
python-dotenv==1.0.1
# 数据校验(FastAPI 内置依赖,无需手动安装,此处显式锁定版本)
pydantic==2.7.1
pydantic-settings==2.2.1
📝 关于 pyproject.toml :现代 Python 项目推荐使用
pyproject.toml替代requirements.txt,类比 Maven 的pom.xml。pyproject.toml是 PEP 517/518 规范定义的统一项目配置文件,支持构建系统声明、元数据、依赖管理一体化。第 12 篇"生产部署"会详细讲解。
pyproject.toml 示例(供参考):
toml
[project]
name = "shop-api"
version = "0.1.0"
description = "FastAPI 系列示例项目"
requires-python = ">=3.11"
# 类比 pom.xml 的 <dependencies>
dependencies = [
"fastapi==0.111.0",
"uvicorn[standard]==0.29.0",
"python-dotenv==1.0.1",
"pydantic==2.7.1",
"pydantic-settings==2.2.1",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
4.4 从 requirements.txt 安装(团队协作)
bash
# 克隆项目后,创建 venv 并安装依赖(类比 mvn install)
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
五、第一个路由
5.1 编写 main.py
在项目根目录创建 main.py:
python
# main.py
# 应用程序入口(类比 Spring Boot 的 Application.java)
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
# lifespan 上下文管理器:管理应用生命周期
# 类比 Spring Boot 的 @PostConstruct(启动初始化)和 @PreDestroy(关闭清理)
@asynccontextmanager
async def lifespan(app: FastAPI):
# ---- 启动阶段(yield 之前) ----
# 在此初始化数据库连接池、加载配置、预热缓存等
# 后续篇章会在此处添加 DB engine 初始化
print("shop-api 启动中...")
yield
# ---- 关闭阶段(yield 之后) ----
# 在此释放资源:关闭连接池、清理临时文件等
print("shop-api 关闭中...")
# 创建 FastAPI 应用实例(类比 Spring Boot 的 SpringApplication.run())
app = FastAPI(
title="Shop API", # 显示在 Swagger UI 顶部
description="FastAPI 系列示例项目 - 简化版电商 REST API",
version="0.1.0",
lifespan=lifespan, # 注册生命周期管理器
# docs_url="/api/docs", # 自定义 Swagger UI 路径(默认 /docs)
# redoc_url="/api/redoc", # 自定义 ReDoc 路径(默认 /redoc)
# openapi_url="/api/openapi.json", # 自定义 OpenAPI 规范路径
)
# CORS 中间件(类比 Spring Boot 的 @CrossOrigin 或 CorsConfigurationSource)
# 第 09 篇"安全与认证"会详细讲解 CORS 配置原则
app.add_middleware(
CORSMiddleware,
# ⚠️ 开发环境可用 * 但注意:allow_origins=["*"] 与 allow_credentials=True 不能同时使用
# CORS 规范禁止 Access-Control-Allow-Origin: * 与 credentials 共存,浏览器会拒绝
# 若需要携带 credentials(Cookie/Authorization),必须指定具体来源,例如:
# allow_origins=["http://localhost:3000", "https://yourdomain.com"]
allow_origins=["*"], # ⚠️ 生产环境必须指定具体域名,禁止使用 *
allow_credentials=False, # credentials 模式下此项须为 False(与 allow_origins=["*"] 共存要求)
allow_methods=["*"], # 允许所有 HTTP 方法
allow_headers=["*"], # 允许所有请求头
)
# 健康检查路由(类比 Spring Boot Actuator 的 /actuator/health)
# tags 参数决定 Swagger UI 中的分组名称
@app.get("/health", tags=["系统"])
async def health_check():
"""
健康检查接口
返回服务运行状态,可被 Kubernetes liveness probe 调用。
"""
return {"status": "ok", "service": "shop-api"}
5.2 启动服务
bash
# 开发模式启动(--reload 监听文件变化自动重启,类比 Spring DevTools)
uvicorn main:app --reload --port 8000
# 输出示例:
# INFO: Will watch for changes in these directories: ['/path/to/shop-api']
# INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
# INFO: Started reloader process [12345] using WatchFiles
# INFO: Started server process [12346]
# INFO: Waiting for application startup.
# shop-api 启动中...
# INFO: Application startup complete.
命令参数说明:
| 参数 | 含义 | Spring Boot 类比 |
|---|---|---|
main:app |
模块名:变量名,指向 FastAPI 实例 | com.example.Application |
--reload |
开发热重载(仅限开发环境) | Spring DevTools |
--port 8000 |
监听端口 | server.port=8000 |
--host 0.0.0.0 |
绑定所有网卡(容器部署必须) | server.address=0.0.0.0 |
--workers 4 |
多进程(仅限非 reload 模式) | server.tomcat.threads.max |
5.3 访问 Swagger UI
服务启动后,打开浏览器访问:
- Swagger UI :
http://127.0.0.1:8000/docs - ReDoc :
http://127.0.0.1:8000/redoc - OpenAPI 规范 :
http://127.0.0.1:8000/openapi.json
Swagger UI 页面会自动展示 /health 接口,包含:
- 接口路径和 HTTP 方法
- 请求/响应模型(来自 Pydantic 类型注解)
- "Try it out" 按钮,可直接在页面发起请求
🎯 与 Spring Boot 的差异 :Spring Boot 需要手动引入
springdoc-openapi-starter-webmvc-ui依赖并配置@OpenAPIDefinition注解才能获得类似效果。FastAPI 的 OpenAPI 文档是框架的核心设计,零配置即用。
5.4 验证健康检查接口
bash
# 使用 curl 验证(类比 Spring Boot Actuator 的健康检查)
curl -s http://127.0.0.1:8000/health | python3 -m json.tool
# 期望输出:
# {
# "status": "ok",
# "service": "shop-api"
# }
六、项目目录结构
6.1 shop-api 完整骨架
良好的目录结构是项目可维护性的基础。以下是 shop-api 的标准分层结构,类比 Spring Boot 的分层架构设计:
shop-api/
├── .venv/ # 虚拟环境(不提交 Git,类比 Maven .m2/)
├── .env # 环境变量(不提交 Git,类比 application-local.yml)
├── .env.example # 环境变量模板(提交 Git,供团队参考)
├── .gitignore
├── requirements.txt # 依赖锁定文件(类比 pom.xml)
├── pyproject.toml # 项目元数据(类比 pom.xml 的项目信息部分)
│
├── main.py # 应用入口(类比 Application.java)
│
├── app/ # 核心应用代码(类比 src/main/java/)
│ ├── __init__.py
│ │
│ ├── core/ # 基础设施(类比 Spring Boot 的 config/ 包)
│ │ ├── __init__.py
│ │ ├── config.py # 配置加载(类比 @ConfigurationProperties)
│ │ ├── database.py # 数据库连接(类比 DataSourceConfig.java)
│ │ ├── security.py # 安全配置(类比 SecurityConfig.java)
│ │ └── exceptions.py # 全局异常处理(类比 @ControllerAdvice)
│ │
│ ├── api/ # 路由层(类比 controller/ 包)
│ │ ├── __init__.py
│ │ ├── deps.py # 公共依赖(类比 Spring 的公共 @Bean)
│ │ └── v1/ # API 版本管理(类比 /api/v1 前缀)
│ │ ├── __init__.py
│ │ ├── router.py # 聚合路由(类比 @RequestMapping 父类)
│ │ ├── products.py # 商品接口(类比 ProductController.java)
│ │ ├── orders.py # 订单接口(类比 OrderController.java)
│ │ └── users.py # 用户接口(类比 UserController.java)
│ │
│ ├── services/ # 业务逻辑层(类比 service/ 包)
│ │ ├── __init__.py
│ │ ├── product_service.py # 商品业务(类比 ProductService.java)
│ │ ├── order_service.py # 订单业务(类比 OrderService.java)
│ │ └── user_service.py # 用户业务(类比 UserService.java)
│ │
│ ├── models/ # 数据模型层(类比 entity/ 包)
│ │ ├── __init__.py
│ │ ├── product.py # 商品实体(类比 Product.java + @Entity)
│ │ ├── order.py # 订单实体(类比 Order.java + @Entity)
│ │ └── user.py # 用户实体(类比 User.java + @Entity)
│ │
│ └── schemas/ # 请求/响应 Schema(类比 dto/ 包)
│ ├── __init__.py
│ ├── product.py # 商品 DTO(类比 ProductDTO.java + @Valid)
│ ├── order.py # 订单 DTO(类比 OrderDTO.java)
│ └── user.py # 用户 DTO(类比 UserDTO.java)
│
└── tests/ # 测试(类比 src/test/java/)
├── __init__.py
├── conftest.py # pytest fixtures(类比 Spring 的 @TestConfiguration)
├── test_health.py # 健康检查测试
└── api/
├── test_products.py
└── test_orders.py
📝 关于
__init__.py:这是 Python 的包标识文件,使目录被 Python 识别为"包"(package)。类似于 Java 中 package 声明的作用,但需要以文件形式存在。内容通常为空或包含包级别的导入。
6.2 与 Spring Boot 分层对比
| FastAPI 目录 | Spring Boot 包 | 职责 |
|---|---|---|
app/api/v1/*.py |
controller/ |
HTTP 请求入口,路由声明,参数绑定 |
app/services/*.py |
service/ |
业务逻辑,事务边界 |
app/models/*.py |
entity/ |
数据库实体映射 |
app/schemas/*.py |
dto/ |
请求/响应数据传输对象 |
app/core/config.py |
config/AppConfig.java |
应用配置 |
app/core/database.py |
config/DataSourceConfig.java |
数据源配置 |
app/core/exceptions.py |
exception/GlobalExceptionHandler.java |
全局异常处理 |
app/api/deps.py |
common/CommonDeps.java |
公共依赖注入 |
tests/conftest.py |
TestConfig.java / @TestConfiguration |
测试公共配置 |
6.3 初始化骨架命令
bash
# 一键创建目录结构
mkdir -p shop-api/{app/{core,api/v1,services,models,schemas},tests/api}
cd shop-api
# 创建所有 __init__.py(Python 包标识)
find app tests -type d | xargs -I{} touch {}/__init__.py
# 创建核心文件
touch main.py \
requirements.txt \
.env \
.env.example \
.gitignore \
app/core/{config,database,security,exceptions}.py \
app/api/{deps,v1/router}.py \
app/api/v1/{products,orders,users}.py \
app/services/{product_service,order_service,user_service}.py \
app/models/{product,order,user}.py \
app/schemas/{product,order,user}.py \
tests/{conftest,test_health}.py \
tests/api/{test_products,test_orders}.py
echo "shop-api 骨架创建完成"
6.4 .gitignore 配置
gitignore
# 虚拟环境(类比 Maven 的 target/ 目录)
.venv/
__pycache__/
*.py[cod]
*.pyo
# 环境变量(含敏感信息,绝对不能提交)
.env
# IDE
.idea/
.vscode/
*.iml
# 测试和覆盖率
.pytest_cache/
.coverage
htmlcov/
# 打包产物
dist/
build/
*.egg-info/
七、常见坑与最佳实践
7.1 虚拟环境未激活
❌ 错误做法:忘记激活 venv,直接使用系统 Python 安装依赖
bash
# ❌ 错误:未激活 venv,依赖安装到系统 Python 中
pip install fastapi
uvicorn main:app # 可能找不到 fastapi,或使用了错误版本
✅ 正确做法:每次新开终端都要激活 venv
bash
# ✅ 正确:先激活 venv
source .venv/bin/activate
# 确认激活状态:终端提示符出现 (.venv) 前缀
# (.venv) user@host:~/shop-api$
# 或通过 which python 确认
which python
# 应输出:/path/to/shop-api/.venv/bin/python
💡 进阶建议 :使用 direnv 工具,在进入项目目录时自动激活 venv,类比 Maven Wrapper(mvnw)的自动化理念。
7.2 生产环境误用 --reload
❌ 错误做法 :在生产环境使用 --reload 标志
bash
# ❌ 错误:生产环境绝对不能用 --reload
# --reload 会启动文件监听进程,占用额外资源
# 更严重的是会意外重启服务,导致请求中断
uvicorn main:app --reload --host 0.0.0.0 --port 8000
✅ 正确做法:生产使用 Gunicorn + Uvicorn Workers(类比 Nginx + Tomcat 反向代理架构)
bash
# ✅ 正确:生产环境使用 gunicorn 管理多 worker
pip install gunicorn
# Gunicorn 作为进程管理器(类比 Spring Boot 的 Tomcat 多线程配置)
# -w 4:启动 4 个 Worker 进程(建议 = 2 * CPU 核数 + 1)
# -k uvicorn.workers.UvicornWorker:每个 Worker 使用 Uvicorn
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
7.3 端口冲突处理
❌ 错误做法:不处理端口冲突,直接强制终止进程
bash
# ❌ 粗暴处理:kill -9 可能导致连接池未正确释放
kill -9 $(lsof -ti:8000)
✅ 正确做法:优雅处理端口冲突
bash
# ✅ 方案一:更换端口
uvicorn main:app --reload --port 8001
# ✅ 方案二:优雅终止占用进程(发送 SIGTERM,等待进程自行清理)
kill -SIGTERM $(lsof -ti:8000)
# ✅ 方案三:查明端口占用原因再决策
lsof -i:8000
# 或
ss -tulnp | grep 8000
7.4 异步函数滥用
❌ 错误做法 :在 async def 路由中调用阻塞 I/O
python
# ❌ 错误:在异步路由中使用阻塞的 requests 库
import requests # 同步 HTTP 客户端
@app.get("/proxy")
async def proxy():
# 这会阻塞整个事件循环,让其他所有请求排队等待!
# 类比:在 Spring WebFlux 的 Mono 中调用 JDBC 同步操作
response = requests.get("https://api.example.com/data")
return response.json()
✅ 正确做法:异步路由使用异步 I/O 库
python
# ✅ 正确:使用 httpx 的异步客户端
import httpx
import requests # 同步客户端(仅用于普通 def 路由)
@app.get("/proxy")
async def proxy():
async with httpx.AsyncClient() as client:
response = await client.get("https://api.example.com/data")
return response.json()
# ✅ 替代方案:如果必须使用同步代码,改用普通 def(FastAPI 会在线程池中运行)
@app.get("/proxy-sync")
def proxy_sync():
# FastAPI 检测到非 async def,自动在线程池执行,不阻塞事件循环
response = requests.get("https://api.example.com/data")
return response.json()
7.5 Pydantic v1 vs v2 混用
⚠️ 注意 :Pydantic v2(2.x)与 v1(1.x)存在重大 Breaking Change,两者不兼容。
python
# ❌ Pydantic v1 写法(过时)
from pydantic import BaseModel
class Product(BaseModel):
class Config: # v1 的配置方式
orm_mode = True # v1 的 ORM 模式
# ✅ Pydantic v2 写法(推荐,FastAPI 0.100+ 默认使用)
from pydantic import BaseModel, ConfigDict
class Product(BaseModel):
model_config = ConfigDict(from_attributes=True) # v2 替代 orm_mode
💡 本系列全程使用 Pydantic v2 ,版本为 2.7.1。如果遇到 ValidationError 或 API 不存在等错误,首先检查 Pydantic 版本。
八、总结
核心概念速查表
| 核心概念 | FastAPI 实现 | Spring Boot 对应 | 说明 |
|---|---|---|---|
| 应用实例 | app = FastAPI() |
SpringApplication.run() |
应用入口,可配置元数据 |
| 路由声明 | @app.get("/path") |
@GetMapping("/path") |
装饰器即路由,简洁直观 |
| 生命周期 | @asynccontextmanager lifespan |
@PostConstruct / @PreDestroy |
管理启动/关闭资源 |
| 数据校验 | Pydantic BaseModel |
@Valid + DTO Bean Validation |
类型注解驱动,自动 422 |
| 依赖注入 | Depends(func) |
@Autowired |
函数式 DI,无 IoC 容器 |
| 中间件 | app.add_middleware() |
Filter / HandlerInterceptor |
请求链路横切处理 |
| ASGI 服务器 | Uvicorn | 内嵌 Tomcat | 实现 HTTP 协议处理 |
| 自动文档 | 内置 /docs /redoc |
springdoc-openapi | 零配置 OpenAPI 文档 |
🎯 金句:FastAPI 不是 Spring Boot 的简化版,而是 Python 生态对"现代 API 框架"的完整回答------类型安全、异步优先、文档即代码。
参考资料
- FastAPI 官方文档 --- 最权威的学习资源,示例丰富
- Starlette 官方文档 --- 了解 FastAPI 底层框架
- Pydantic v2 官方文档 --- 数据校验核心库
- Uvicorn 官方文档 --- ASGI 服务器配置参考
- Python asyncio 官方文档 --- 理解异步编程基础
- ASGI 规范 --- 理解 ASGI 协议设计
- PEP 518 --- pyproject.toml --- 现代 Python 项目配置规范
补充:配置管理入门
配置加载(app/core/config.py)
FastAPI 推荐使用 pydantic-settings 管理配置,类比 Spring Boot 的 application.yml + @ConfigurationProperties。
python
# app/core/config.py
# 应用配置管理(类比 Spring Boot 的 @ConfigurationProperties)
from pydantic_settings import BaseSettings, SettingsConfigDict
from functools import lru_cache
class Settings(BaseSettings):
"""
应用配置类,字段值优先从环境变量读取,其次使用默认值。
类比 Spring Boot 的 @ConfigurationProperties(prefix="app")
"""
# 应用基础配置
app_name: str = "Shop API"
app_version: str = "0.1.0"
debug: bool = False # 类比 spring.profiles.active=dev
# 服务配置
host: str = "0.0.0.0"
port: int = 8000
# 数据库配置(第 03 篇会用到)
database_url: str = "sqlite:///./shop.db" # 默认使用 SQLite
# JWT 安全配置(第 09 篇会用到)
secret_key: str = "change-me-in-production"
access_token_expire_minutes: int = 30
# pydantic-settings 配置:从 .env 文件加载
# 类比 Spring Boot 的 @PropertySource("classpath:application.yml")
model_config = SettingsConfigDict(
env_file=".env", # 读取 .env 文件
env_file_encoding="utf-8",
case_sensitive=False, # 环境变量名大小写不敏感
)
# @lru_cache 确保 Settings 只实例化一次(单例模式)
# 类比 Spring 的 @Bean + @Scope("singleton")
@lru_cache
def get_settings() -> Settings:
return Settings()
.env 文件示例(开发环境):
bash
# .env(不提交 Git!)
APP_NAME=Shop API (Dev)
DEBUG=true
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/shopdb
SECRET_KEY=dev-only-secret-key-replace-in-production
.env.example 文件(提交 Git,作为团队配置模板):
bash
# .env.example(提交 Git,供团队成员参考)
APP_NAME=Shop API
DEBUG=false
DATABASE_URL=postgresql+asyncpg://user:password@host:5432/shopdb
SECRET_KEY=your-secret-key-here
ACCESS_TOKEN_EXPIRE_MINUTES=30
在路由中使用配置
python
# 在路由中注入配置(类比 Spring 的 @Value 注入)
from fastapi import Depends
from app.core.config import Settings, get_settings
@app.get("/info", tags=["系统"])
async def app_info(settings: Settings = Depends(get_settings)):
"""
返回应用基础信息(仅在 debug 模式下暴露详细信息)
"""
if not settings.debug:
return {"name": settings.app_name, "version": settings.app_version}
# debug 模式下返回更多信息(类比 Spring Boot Actuator 的 /info endpoint)
return {
"name": settings.app_name,
"version": settings.app_version,
"debug": settings.debug,
"host": settings.host,
"port": settings.port,
}
💡 设计要点 :
get_settings()加了@lru_cache,结合Depends()使用时,整个应用生命周期内只会创建一个Settings实例,符合单例语义。这是 FastAPI 中实现"配置单例"的惯用模式。
补充:异步编程基础
同步 vs 异步:从 Java 线程模型到 Python asyncio
对于 Spring Boot 工程师来说,Python 的 asyncio 是理解 FastAPI 性能优势的关键。
Spring Boot 的并发模型(传统 Servlet 模型):
Request 1 --> Thread-1 [处理中... 等待DB...]
Request 2 --> Thread-2 [处理中... 等待DB...]
Request 3 --> Thread-3 [处理中... 等待DB...]
...(线程池满后,新请求排队等待)
FastAPI 的并发模型(asyncio 事件循环):
Single Thread (Event Loop)
|- Request 1: 发起 DB 查询 --> 挂起,处理下一个
|- Request 2: 发起 HTTP 调用 --> 挂起,处理下一个
|- Request 3: 业务逻辑 --> 执行完毕,返回
|- DB 查询完成 --> 恢复 Request 1,继续处理
|- HTTP 调用完成 --> 恢复 Request 2,继续处理
🤔 理解关键 :asyncio 的优势在于 I/O 等待期间不占用线程。对于 API 服务这类 I/O 密集型场景(大量时间花在等待数据库、缓存、第三方 API 响应上),单线程 + 事件循环的吞吐量可以远超多线程模型。这与 Spring WebFlux(Project Reactor)的设计思想完全一致。
async/await 基础语法
📝 以下代码需追加到
main.py中,app对象已在该文件定义。
python
# 异步函数示例:理解 async/await 的执行流程
import asyncio
# 模拟数据库查询(类比 Spring Data JPA 的 findById)
async def fetch_product_from_db(product_id: int) -> dict:
"""模拟异步数据库查询(I/O 操作)"""
# asyncio.sleep 是非阻塞的,会把控制权交还给事件循环
# 类比:Java 中的 CompletableFuture.supplyAsync(...)
await asyncio.sleep(0.1) # 模拟 100ms 数据库延迟
return {"id": product_id, "name": f"Product {product_id}", "price": 99.9}
# ✅ 异步路由:适合 I/O 密集型操作
@app.get("/products/{product_id}", tags=["商品"])
async def get_product(product_id: int):
# await 暂停当前协程,让出事件循环处理其他请求
# 当 fetch_product_from_db 完成后,协程恢复执行
product = await fetch_product_from_db(product_id)
return product
# ✅ 同步路由:适合 CPU 密集型操作(FastAPI 会自动在线程池中运行)
@app.get("/compute/{n}", tags=["工具"])
def fibonacci(n: int):
"""CPU 密集型任务使用同步函数,FastAPI 自动放入线程池"""
if n <= 1:
return {"result": n}
a, b = 0, 1
for _ in range(2, n + 1):
a, b = b, a + b
return {"n": n, "result": b}
⚠️ 性能陷阱 :不要在 async def 路由中调用任何阻塞操作(time.sleep()、同步数据库驱动、requests.get() 等)。若必须执行阻塞操作,改用普通 def,FastAPI 会自动将其放入线程池执行。
补充:完整的健康检查实现
💡 以下是对第五章
/health接口的完整升级版本,读者可直接替换main.py中原有的health_check函数。
实际生产项目中,健康检查接口需要检测关键依赖(数据库、缓存等)的可用性,而非仅返回一个固定响应。以下是更完整的实现示例:
python
# 完整的健康检查实现(生产级)
# 类比 Spring Boot Actuator 的 HealthIndicator
import time
from enum import Enum
from fastapi import FastAPI
from pydantic import BaseModel
class HealthStatus(str, Enum):
"""健康状态枚举"""
OK = "ok"
DEGRADED = "degraded" # 部分功能不可用
DOWN = "down" # 服务不可用
class ComponentHealth(BaseModel):
"""单个组件健康状态(类比 Spring Actuator 的 Health 对象)"""
status: HealthStatus
details: dict = {}
class HealthResponse(BaseModel):
"""整体健康检查响应"""
status: HealthStatus
service: str
version: str
uptime_seconds: float
components: dict[str, ComponentHealth] = {}
# 记录服务启动时间
_start_time = time.time()
@app.get(
"/health",
tags=["系统"],
response_model=HealthResponse, # 声明响应模型(类比 @ApiResponse)
summary="健康检查",
description="检查服务及其依赖组件的运行状态",
)
async def health_check() -> HealthResponse:
"""
健康检查接口
- **status**: 整体状态(ok / degraded / down)
- **uptime_seconds**: 服务已运行秒数
- **components**: 各依赖组件的健康状态
"""
uptime = time.time() - _start_time
# 检查各组件健康状态(后续篇章会替换为真实检查)
components: dict[str, ComponentHealth] = {
"database": ComponentHealth(
status=HealthStatus.OK,
details={"type": "sqlite", "latency_ms": 0},
),
}
# 计算整体状态:任意组件 DOWN -> 整体 DOWN;任意 DEGRADED -> 整体 DEGRADED
all_statuses = [c.status for c in components.values()]
if HealthStatus.DOWN in all_statuses:
overall = HealthStatus.DOWN
elif HealthStatus.DEGRADED in all_statuses:
overall = HealthStatus.DEGRADED
else:
overall = HealthStatus.OK
return HealthResponse(
status=overall,
service="shop-api",
version="0.1.0",
uptime_seconds=round(uptime, 2),
components=components,
)
访问 http://127.0.0.1:8000/health 将返回:
json
{
"status": "ok",
"service": "shop-api",
"version": "0.1.0",
"uptime_seconds": 42.15,
"components": {
"database": {
"status": "ok",
"details": {
"type": "sqlite",
"latency_ms": 0
}
}
}
}
📝 Kubernetes 集成建议 :将
/health用于 liveness probe (服务是否存活),可额外提供/ready用于 readiness probe(服务是否就绪接受流量)。这两个探针语义不同:liveness 失败触发 Pod 重启,readiness 失败只是暂停流量路由。
下期预告
第 02 篇:路由与请求模型------把 Spring MVC 的 @RequestMapping 翻译成 FastAPI
下一篇将深入讲解:
- 路径参数、查询参数、请求体的完整声明方式(对标
@PathVariable、@RequestParam、@RequestBody) - Pydantic
BaseModel进阶:字段校验、默认值、嵌套模型(对标 Bean Validation 注解) shop-api商品模块第一个真实 CRUD 接口:POST /api/v1/products- 响应模型(
response_model)与 Spring Boot@ResponseBody的对比 - 路由分组与
APIRouter(对标 Spring MVC 的@RequestMapping类级注解)
敬请期待 🚀