# 请求处理器(Handler) Handler 层是 HTTP 接口层,负责接收请求、校验权限、记录操作日志,然后委托给 Service 层处理。每个业务模块对应一个 `handlers.py` 文件,所有 Handler 继承 `BaseHandler`。 ## 文件位置 ``` src/modules/link/handlers.py ``` ## 完整代码 ```python from common.middleware.access_decorators import check_demo, permission_required from common.middleware.operation_log import operation_log from core import response as R from core.base_handler import BaseHandler from modules.link.service import link_service class LinkPageHandler(BaseHandler): """查询友链分页数据。""" @permission_required("sys:link:list") async def get(self): return await link_service.get_page(self) class LinkDetailHandler(BaseHandler): """查询友链详情。""" @permission_required("sys:link:detail") async def get(self, id): return R.ok(self, data=link_service.get_detail(id)) class LinkAddHandler(BaseHandler): """添加友链。""" @permission_required("sys:link:add") @check_demo @operation_log("友链管理", "添加") async def post(self): return await link_service.add(self) class LinkUpdateHandler(BaseHandler): """更新友链。""" @permission_required("sys:link:update") @check_demo @operation_log("友链管理", "更新") async def put(self): return await link_service.update(self) class LinkDeleteHandler(BaseHandler): """删除友链。""" @permission_required("sys:link:delete") @check_demo @operation_log("友链管理", "删除") async def delete(self, id): return await link_service.delete(self, id) class LinkStatusHandler(BaseHandler): """设置友链状态。""" @permission_required("sys:link:status") @check_demo @operation_log("友链管理", "设置状态") async def put(self): return await link_service.update_status(self) class LinkBatchDeleteHandler(BaseHandler): """批量删除友链。""" @permission_required("sys:link:delete") @check_demo @operation_log("友链管理", "批量删除") async def post(self): return await link_service.batch_delete(self) ``` ## 代码解析 ### Handler 类 ```python class LinkPageHandler(BaseHandler): ``` 每个 Handler 继承 `BaseHandler`(即 `tornado.web.RequestHandler`),负责一个 HTTP 端点。与 Tornado 的 Endpoint 函数不同,Tornado 使用类来组织处理器。 ### 装饰器说明 | 装饰器 | 作用 | 位置 | |:----|:----|:----| | `@permission_required("sys:link:list")` | RBAC 权限校验 | 类方法上 | | `@check_demo` | 演示模式拦截(仅写操作) | 权限装饰器之后 | | `@operation_log("模块", "动作")` | 操作日志记录 | 最内层 | **装饰器顺序必须严格遵守**:权限 → 演示模式 → 操作日志。 ### 路径参数 ```python async def get(self, id): ``` Tornado 的路径参数通过正则捕获组传入方法参数。路由定义 `(r"/link/detail/(\d+)", LinkDetailHandler)` 中的 `(\d+)` 对应 `id` 参数。 ### 响应封装 - **Service 返回 R 对象的**(如 `add`、`update`、`delete`):直接 `return` - **Service 返回原始数据的**(如 `get_detail`):用 `R.ok(self, data=...)` 包装 ### HTTP 方法映射 | 操作 | HTTP 方法 | Handler 方法 | |:----|:----|:----| | 分页查询 | GET | `async def get(self)` | | 详情查询 | GET | `async def get(self, id)` | | 新增 | POST | `async def post(self)` | | 更新 | PUT | `async def put(self)` | | 删除 | DELETE | `async def delete(self, id)` | | 状态变更 | PUT | `async def put(self)` | | 批量删除 | POST | `async def post(self)` | ### 权限字符串命名规范 ``` sys:{module}:{action} ``` | 动作 | HTTP 方法 | 说明 | |:----|:----|:----| | `list` | GET | 分页/列表查询 | | `detail` | GET | 详情查询 | | `add` | POST | 新增 | | `update` | PUT | 更新 | | `delete` | DELETE | 单条/批量删除 | | `status` | PUT | 状态变更 | ## 开发要点 1. **Handler 层不含业务逻辑**:仅做权限校验、日志记录和请求分发 2. **装饰器顺序**:权限 → 演示模式 → 操作日志 3. **写操作必须加 `@check_demo`**:防止演示环境被修改 4. **写操作建议加 `@operation_log`**:记录操作日志用于审计 5. **所有方法都是 `async def`**:Tornado Handler 方法默认异步 ## 总结 Handler 层是 HTTP 请求的入口,负责权限校验、操作日志记录和请求分发,不含业务逻辑。装饰器顺序固定为权限 → 演示模式 → 操作日志,写操作必须加 `@check_demo`,所有逻辑委托 Service 处理。