FastAPI 系列(一)· 初体验——从 Spring Boot 工程师视角认识 FastAPI

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.xmlpyproject.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 UIhttp://127.0.0.1:8000/docs
  • ReDochttp://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 框架"的完整回答------类型安全、异步优先、文档即代码。


参考资料


补充:配置管理入门

配置加载(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 类级注解)

敬请期待 🚀

相关推荐
AI玫瑰助手3 小时前
Python流程控制:pass语句的作用与使用场景
开发语言·python·信息可视化
Metaphor6923 小时前
使用 Python 设置 Word 文档文本的颜色
python·word
ping某3 小时前
Nginx 内嵌 CPython 3.5→3.8 升级实录
后端
vx-程序开发3 小时前
springboot课程管理系统-计算机毕业设计源码16731
spring boot·后端·课程设计
stark张宇3 小时前
支付宝 App 支付踩坑记:x509 证书不匹配 & 应用未上线问题解决
后端·支付宝
MacroZheng3 小时前
IDEA + 阿里 Qoder = 王炸!
java·人工智能·后端
肥胖小羊3 小时前
基于状态机的客户生命周期流转与自动化触达引擎实现
开发语言·python
深度学习lover3 小时前
<数据集>yolo 易拉罐识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·易拉罐识别