处理重复复杂异常逻辑的最优方案?面向API端点场景的实现咨询
通用优化方案
你的第三种方案是方向最正确的,只需要做两个小优化就能解决所有问题,同时兼顾简洁性、可读性和职责合理性:
第一步:定义带业务属性的自定义异常基类
让所有业务异常继承同一个基类,内置错误提示、状态码等通用属性,避免异常处理逻辑里写大量的类型判断:
class BusinessError(Exception): def __init__(self, error_msg: str, status_code: int = 400): self.error_msg = error_msg self.status_code = status_code super().__init__(error_msg) # 具体业务异常直接继承即可 class UserDoesNotExist(BusinessError): def __init__(self): super().__init__("No such user", status_code=404) class MissingPermission1(BusinessError): def __init__(self): super().__init__("No permission 1", status_code=403)
get_user方法保持纯逻辑,只负责查询用户和校验权限,不符合条件直接抛对应异常即可,不需要处理响应和连接关闭:
def get_user(self, user_id): user = self.database.lookup(user_id) if not user: raise UserDoesNotExist if not user.hasPermission(1): raise MissingPermission1 return user
第二步:封装重复的异常处理逻辑
用装饰器抽离所有端点重复的异常捕获、响应写入、连接关闭逻辑,完全消除重复代码:
def handle_business_error(func): def wrapper(self, *args, **kwargs): try: return func(self, *args, **kwargs) except BusinessError as e: self.write(e.error_msg) # 框架支持设置状态码的话可以补充 if hasattr(self, 'set_status'): self.set_status(e.status_code) self.connection.close() return # 兜底处理非业务预期的异常 except Exception as e: self.write("Internal server error") self.connection.close() return return wrapper
最终端点代码
端点只需要关注核心业务逻辑,没有任何冗余代码:
class MyHandler(tornado.web.RequestHandler): @handle_business_error def endpoint_1(self, user_id): user = self.get_user(user_id) # 直接写业务逻辑即可,不需要处理异常、关闭连接 ... @handle_business_error def endpoint_2(self, user_id): user = self.get_user(user_id) ...
额外适配场景
- 如果绝大多数端点都需要用户校验,可以把
get_user的调用放到请求前置拦截层(比如Tornado的prepare方法、其他框架的中间件/拦截器),连每个端点里调用get_user的代码都可以省略。 - 该方案完全不绑定框架,任意语言都可以用对应特性实现:Java用AOP切接口层、Go用中间件套路由、JS用高阶函数封装接口处理逻辑,核心思路完全一致。
内容的提问来源于stack exchange,提问作者Zigsaz
相关产品推荐
相关产品推荐

