Skip to content

全局异常与响应

项目定义了统一的响应格式和全局异常处理机制。所有 API 返回 {code, data, msg, ok} 标准格式,异常被捕获后也转换为相同格式。响应函数位于 src/core/response.py,异常类型位于 src/core/exceptions.py。

统一响应格式 ​

src/core/response.py 提供统一的响应生成函数:

python
from src.core import response as R

# 成功响应
R.ok(data={"id": 1}, msg="操作成功")
# {"code": 0, "data": {"id": 1}, "msg": "操作成功", "ok": true}

# 成功响应(带额外字段)
R.ok(data=list, count=total)
# {"code": 0, "data": [...], "msg": "操作成功", "ok": true, "count": 100}

# 失败响应
R.failed(msg="参数错误")
# {"code": 1, "data": null, "msg": "参数错误", "ok": false}

响应函数说明 ​

函数说明codeok
R.ok()成功响应0true
R.failed()失败响应1false
R.page()分页响应0true
R.response()通用响应自定义自定义

函数签名:

python
def ok(data=None, msg="操作成功", code=0, **kwargs):
    """生成成功响应,支持通过 kwargs 添加额外字段(如 count)"""
    return jsonify({"code": code, "data": data, "msg": msg, "ok": True, **kwargs})

def failed(msg="操作失败", code=1, data=None, **kwargs):
    """生成失败响应"""
    return jsonify({"code": code, "data": data, "msg": msg, "ok": False, **kwargs})

def page(data: list, total: int, current: int, size: int, msg="操作成功", code=0):
    """分页响应:封装 {records, total, size, current, pages} 标准分页结构"""
    pages = (total + size - 1) // size if size > 0 else 0
    return jsonify({
        "code": code,
        "data": {"records": data, "total": total, "size": size, "current": current, "pages": pages},
        "msg": msg,
        "ok": True
    })

def response(data=None, msg="操作成功", code=0, success=True, **kwargs):
    """通用响应生成器(高级用法),允许完全自定义字段"""
    return jsonify({"code": code, "data": data, "msg": msg, "ok": success, **kwargs})

分页响应 ​

python
R.page(data=records, total=100, current=1, size=10)
# {
#     "code": 0,
#     "data": {
#         "records": [...],
#         "total": 100,
#         "size": 10,
#         "current": 1,
#         "pages": 10
#     },
#     "msg": "操作成功",
#     "ok": true
# }

异常类型 ​

BizError ​

业务异常,业务代码可主动抛出:

python
# src/core/exceptions.py
class BizError(Exception):
    def __init__(self, msg: str = "操作失败", code: int = 1):
        self.code = code
        self.msg = msg
        super().__init__(msg)

使用示例:

python
from src.core.exceptions import BizError

def some_business_logic():
    if some_condition:
        raise BizError(msg="数据不存在")

ValidationError ​

参数验证异常,由 WTForms 校验失败时抛出:

python
from wtforms import ValidationError

class PositionForm(BaseForm):
    name = StringField('岗位名称', validators=[...])

    def validate_name(self, field):
        if some_condition:
            raise ValidationError('岗位名称已存在')

全局异常处理器 ​

src/app.py 注册了全局异常处理器,捕获所有异常并转换为标准格式:

python
def register_exception(app):
    # 业务异常
    @app.errorhandler(BizError)
    def biz_error_handler(exc):
        return R.failed(msg=exc.msg, code=exc.code)

    # 参数验证异常
    @app.errorhandler(ValidationError)
    def validation_error_handler(exc):
        return R.failed(msg=str(exc))

    # HTTP 异常(404/405 等)
    @app.errorhandler(404)
    def not_found_handler(exc):
        return R.failed(msg="请求的资源不存在")

    @app.errorhandler(405)
    def method_not_allowed_handler(exc):
        return R.failed(msg="请求方法不允许")

    # 未捕获异常
    @app.errorhandler(Exception)
    def exception_handler(exc):
        # 记录异常日志
        app.logger.error(f"未捕获异常: {exc}", exc_info=True)
        return R.failed(msg="服务器内部错误")

HTTP 200

所有异常响应均返回 HTTP 200 状态码,业务状态通过 code 字段区分。这是前后端分离架构的常见做法,避免浏览器拦截非200响应。

状态码常量 ​

python
# src/core/response.py
class Codes:
    SUCCESS = 0
    FAILED = 1
    UNAUTHORIZED = 401  # 未认证
    FORBIDDEN = 403     # 无权限
    NOT_FOUND = 404     # 资源不存在
    VALIDATE_ERROR = 422  # 验证错误
    SERVER_ERROR = 500   # 服务器错误

异常处理流程 ​

请求进入
    ↓
路由匹配
    ↓
视图函数执行
    ├─ 正常返回 → R.ok() / R.failed()
    ├─ 抛出 BizError → biz_error_handler → R.failed()
    ├─ 抛出 ValidationError → validation_error_handler → R.failed()
    ├─ 抛出 HTTP 异常 → http_exception_handler → R.failed()
    └─ 抛出其他异常 → exception_handler → R.failed()
    ↓
返回 JSON 响应

总结 ​

全局异常与响应模块具备以下特点:

1. 统一格式:所有 API 返回 {code, data, msg, ok} 标准格式
2. 全局捕获:业务异常、验证异常、HTTP异常、未捕获异常
3. HTTP 200:所有响应均返回 200,业务状态通过 code 区分
4. 错误聚合:多个验证错误用 / 分隔,便于前端展示
5. 安全隐藏:未捕获异常返回通用提示,不暴露内部错误信息
6. 日志记录:未捕获异常会记录详细日志,便于排查问题

小蚂蚁云团队 · 提供技术支持