--- author: Peanut created_at: 2026-05-23 purpose: 设计 web-admin 接口管理功能,通过解析 OpenAPI JSON 实现接口发现、管理和测试 --- # 接口管理功能设计文档 ## 1. 架构概览 Spring Boot 启动时通过 ApplicationRunner 解析本机 `/api/v3/api-docs` 的 OpenAPI JSON,在事务中全量更新数据库(删除旧数据 → 解析 → 批量插入)。前端从数据库查询接口列表,支持分页、按标签/方法/路径/operationId 搜索。接口测试面板支持三种 Token 来源:当前管理员 Token、手动输入、用户端登录获取并自动保存。后端提供代理测试接口,仅限管理员访问,仅允许转发到本地 `/api/*` 路径,避免 SSRF。 ## 2. 数据库设计 ### 接口主表 api_endpoint ```sql CREATE TABLE api_endpoint ( id VARCHAR(64) PRIMARY KEY, path VARCHAR(500) NOT NULL, method VARCHAR(10) NOT NULL, operation_id VARCHAR(200), summary VARCHAR(500), description TEXT, tags VARCHAR(500), deprecated TINYINT(1) DEFAULT 0, request_schema JSON, response_schema JSON, create_by VARCHAR(64), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_by VARCHAR(64), update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, is_deleted TINYINT(1) DEFAULT 0, remarks VARCHAR(500), UNIQUE INDEX idx_operation_id (operation_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` ### 参数表 api_param ```sql CREATE TABLE api_param ( id VARCHAR(64) PRIMARY KEY, endpoint_id VARCHAR(64) NOT NULL, param_type VARCHAR(20) NOT NULL, name VARCHAR(100) NOT NULL, required TINYINT(1) DEFAULT 0, param_type_def VARCHAR(50), description VARCHAR(500), default_value VARCHAR(200), enum_values JSON, example VARCHAR(500), INDEX idx_endpoint (endpoint_id), FOREIGN KEY (endpoint_id) REFERENCES api_endpoint(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` **说明**:实体类继承项目已有的 `BaseEntity`(含 id、createBy、createTime、updateBy、updateTime、isDeleted、remarks),使用 `IdType.ASSIGN_UUID` 生成 UUID 主键。 ## 3. 后端服务设计 ### 新增文件 | 文件 | 职责 | |---|---| | `entity/ApiEndpoint.java` | 继承 BaseEntity | | `entity/ApiParam.java` | 继承 BaseEntity | | `mapper/ApiEndpointMapper.java` | BaseMapper | | `mapper/ApiParamMapper.java` | BaseMapper | | `dto/request/ApiEndpointListRequest.java` | 继承 BasePageRequest,添加 method、tags 过滤 | | `dto/response/ApiEndpointItemResponse.java` | 列表项 | | `dto/response/ApiEndpointDetailResponse.java` | 详情 + 参数列表 | | `dto/request/ApiTestProxyRequest.java` | 代理测试入参 | | `service/ApiEndpointService.java` | 解析 OpenAPI JSON、同步、查询 | | `service/ApiEndpointSyncRunner.java` | @Component + ApplicationRunner,启动时触发 | | `controller/ApiEndpointController.java` | 路由前缀 /endpoint | | `controller/ApiTestProxyController.java` | 路由前缀 /endpoint/test,管理员专用 | ### 同步逻辑(ApiEndpointService.syncFromOpenApi()) 1. 通过 RestTemplate 请求 `http://127.0.0.1:{port}/api/v3/api-docs`(port 从配置文件读取) 2. 若请求失败,记录 WARN 日志,不阻断启动 3. `@Transactional` 包裹:DELETE FROM api_param → DELETE FROM api_endpoint 4. 遍历 `paths` → `method` → 解析每个 endpoint 5. 提取 tags、summary、description、operationId、requestSchema、responseSchema 6. 从 `parameters` 数组解析参数列表(query/path/header/cookie) 7. 从 `requestBody.content` 解析 body schema 8. `$ref` 展开为内联 schema,最大展开深度 10 层 9. 批量插入 endpoint → 批量插入 param ### 后端接口(无 /api 前缀,通过网关转发) | 方法 | 路径 | 说明 | 权限 | |---|---|---|---| | POST | /admin/endpoint/list | 分页查询,关键词同时搜索 path/summary/operation_id | 管理员 | | GET | /admin/endpoint/detail | 查询详情 + 参数列表 | 管理员 | | POST | /admin/endpoint/sync | 手动触发同步,同步耗时较长,返回 task ID | 管理员 | | POST | /admin/endpoint/test | 代理测试请求,仅允许 /api/* 路径 | 管理员 | ### 代理测试安全控制 - 仅允许转发到 `/api/*` 路径,拒绝其他 URL(SSRF 防护) - 仅管理员可访问(AdminAuthInterceptor 拦截 /admin/**) - 默认 30s 超时,超时返回明确错误信息 - 非 JSON 响应限制展示前 2000 字符,HTML 内容做转义处理 ### 同步接口异步化 手动同步(`/admin/endpoint/sync`)采用 `@Async` 异步执行,返回 `{ taskId: "xxx" }`,前端通过轮询 `/admin/endpoint/sync/status/{taskId}` 获取同步进度和结果。ApplicationRunner 的启动同步同样异步,不阻塞应用启动。 ## 4. 前端页面设计 ### 菜单位置 在现有 **开发工具** 分组下新增 "接口管理" 子菜单。 ### 接口列表页 - 搜索条件:关键词(覆盖 path、summary、operation_id)、HTTP 方法下拉、标签下拉 - 表格列:方法(颜色标签区分)、路径、简述、标签、更新时间 - 操作列:[详情] 按钮 - 顶部:[手动同步] 按钮(触发后显示同步进度提示) ### 接口详情/测试弹窗 点击"详情"弹出对话框,包含两个标签页: **详情标签**: - 路径、方法、描述 - 参数列表表格(类型、名称、必填、描述、示例) - 响应结构 JSON 展示 **测试标签**: - Token 来源选择(单选): - 使用当前管理员 Token(默认) - 手动输入文本框 - 用户端登录获取(输入手机号/验证码,成功后自动保存 Token 到 localStorage) - 参数表单:根据接口参数自动生成输入框 - [发送请求] 按钮 - 响应结果区域:状态码、耗时、JSON 格式化展示 ## 5. 错误处理与边界情况 | 场景 | 处理方式 | |---|---| | `/v3/api-docs` 请求失败 | 记录 WARN 日志,不阻断启动,提供手动同步 | | 同步中途异常 | `@Transactional` 回滚,下次同步全量替换 | | 数据库为空 | 前端显示空状态提示 + 手动同步按钮 | | 测试代理超时 | 返回 `Result.error("代理请求超时(30s),目标接口可能响应过慢或不可达")` | | 非 JSON 响应 | 展示前 2000 字符,HTML 转义,二进制返回类型提示 | | Token 保存 | 管理员 Token 走现有机制,手动 Token 仅内存使用,用户端 Token 存 localStorage | | `$ref` 循环引用 | 最大展开深度 10 层,超限保留 `$ref` 并提示 | | 文件上传接口 | 本期不支持,后续迭代 |