外观
异常与响应规范
异常处理规范
异常处理策略
| 层级 | 核心职责 | 是否使用try-except | 异常处理方式 |
|---|---|---|---|
| API 路由层 | 接收请求、调用 Service、返回统一响应 | 不需要(特殊中间件除外) | 不处理异常,让异常向上抛至全局兜底 |
| 业务服务层 | 实现核心业务逻辑,协调 DB / 第三方服务调用 | 必须使用 | 捕获底层技术异常,抛出自定义业务异常 |
| 数据库操作层 | 纯数据库 CRUD 操作,无任何业务判断 | 不使用 | 不处理异常,直接抛给上层服务层 |
示例
反面例子:路由层处理异常
- 破坏了分层职责,导致路由层臃肿,且重复定义异常返回格式,破坏全局一致性
python
@router.post("/kb", summary="创建知识库")
async def create_kb(db: AsyncSession, kb_data: KnowledgeBaseCreateSchema):
try:
result = await KnowledgeBaseService.create_kb_service(db, kb_data)
return SuccessResponse(data=result)
except Exception as e:
# 错误:路由层处理异常,重复定义返回格式
return JSONResponse(status_code=400, content={"code": 400, "msg": str(e)})正确做法:服务层抛异常
- 不需要在每个路由里写 try-except 来“防止 500” —— 全局兜底已经做了这件事。
- try-except 应该用在 Service 层(或更靠近业务逻辑的地方),关键是异常的语义转换与业务可读性
- 核心原则:异常的语义转换。在适当的地方使用 try-except,目的不是“防止程序崩溃”,而是“将底层/第三方异常转化为业务语义明确的自定义异常
python
### API 路由层
@router.post(...)
async def create_kb(...):
# 不需要 try-except!让异常向上抛
result = await KnowledgeBaseService.create_kb_service(db, kb_data)
return SuccessResponse(data=result)
### 业务服务层:捕获底层异常,抛出自定义业务异常
from app.config.exception_config import BusinessException
class KnowledgeBaseService:
@staticmethod
async def create_kb_service(db: AsyncSession, kb_data: KnowledgeBaseCreateSchema):
try:
# 比如数据库唯一约束冲突、第三方 API 失败等
kb = KnowledgeBase(name=kb_data.name)
db.add(kb)
await db.commit()
return kb
except IntegrityError as e:
# 业务异常
raise BusinessException(code=400, msg="知识库名称已存在")
except SomeThirdPartyError as e:
raise BusinessException(code=502, msg="依赖服务不可用", data=str(e))相关代码
异常相关代码:app\config\exception_config.py
接口响应规范
统一接口响应
统一业务状态码规范:
- 成功:code 200
- 失败:code 非200
统一接口响应配置:app\config\response_config.py
python
from typing import Optional, Generic, TypeVar
from pydantic import BaseModel
T = TypeVar("T")
class SuccessResponse(BaseModel, Generic[T]):
"""
统一成功响应模型
业务状态码规范:
- 成功:code 200
- 失败:code 非200
"""
code: int = 200
msg: str = "成功"
data: Optional[T] = None示例
成功

失败
