# WorkUtils API 本地调试代理启动设计 ## 目标 WorkUtils 进程启动时自动启动 API 文档调试所需的本地 HTTP 代理。用户无需进入 API 导出页面、勾选复选框或点击导出按钮来启动代理。API 导出页面删除代理开关,并持续展示代理已启动或启动失败的只读状态。 ## 范围 - 代理随 WorkUtils 的 `CommandLineRunner` 生命周期启动,GUI 和命令行入口使用同一套逻辑。 - 代理失败不得阻止 WorkUtils 主界面或命令行功能继续运行。 - API 导出始终读取应用启动阶段确定的代理端点;启动失败时端点为空,文档仍可导出,但接口调试功能不可用。 - WorkUtils 运行结束时主动停止 HTTP Server 和代理线程池。 - 不新增配置项,不持久化代理端口,不改变代理的随机本机端口策略。 ## 架构 新增一个 Spring 单例生命周期服务,作为应用入口、API 插件和代理实现之间的唯一边界。服务负责: 1. 幂等启动 `DubboDebugProxy`; 2. 捕获启动异常并保存不可变状态; 3. 向 UI 和导出用例提供端点或失败原因; 4. 在应用运行结束时幂等关闭代理。 `WorkUtilsApplication.run(...)` 在分派 GUI 或命令行操作前调用生命周期服务的启动方法,并在运行结束的 `finally` 中关闭代理。这样代理会在任何 API 页面构造之前启动,也不会依赖可能晚于阻塞式窗口循环的 `ApplicationReadyEvent`。 `ApiDocPlugin` 注入同一个生命周期服务并传给 `ApiDocWindow`。页面只读取状态,不创建、重启或关闭代理。 ## 状态模型 生命周期服务公开不可变状态,状态仅允许以下三种结果: - `NOT_STARTED`:仅用于应用启动调用发生前和单元测试初始化; - `RUNNING`:包含非空的 `http://127.0.0.1:{port}/dubbo/invoke` 地址; - `FAILED`:包含可展示的失败原因,端点为空。 重复调用启动方法不得创建第二个代理实例。重复调用关闭方法不得抛出异常。 ## API 导出页面 删除“启用接口调试(启动本地代理)”复选框。原位置显示只读状态标签: - 成功:`● 本地代理已启动:http://127.0.0.1:{port}/dubbo/invoke` - 失败:`● 本地代理启动失败:{错误原因}` 成功状态使用现有成功色,失败状态使用现有危险色。失败标签提供包含完整错误原因的 Tooltip 和 accessible text。状态标签不提供启动、重试或关闭操作。 ## 导出数据流 `ApiDocExportRequest` 删除 `debugProxyEnabled` 字段和所有对应工厂参数。`RunApiDocExportUseCase` 每次执行都从注入的端点供应器读取当前地址,并将非空地址交给导出器。代理启动失败时供应器返回空字符串,导出照常进行,API 页面日志追加“本地代理不可用,导出文档的接口调试功能已禁用”。 页面不再持有代理复选框,也不再从 UI 控件构造代理选择状态。 ## 代理关闭 `DubboDebugProxy` 增加幂等 `stop()`:停止 `HttpServer`,关闭其专用 `ExecutorService`。代理不复用全局任务执行器,防止关闭代理影响其他业务任务。 ## 错误处理 - 启动失败:生命周期服务捕获异常、记录错误、保存 `FAILED` 状态,WorkUtils 继续运行。 - UI 展示:API 页面读取失败状态并展示短原因;完整原因放入 Tooltip。 - 导出降级:空端点不阻止 HTML/Markdown 生成,只禁用生成文档中的发送调试请求能力。 - 关闭失败:记录警告,不覆盖原始业务异常,也不阻止进程退出。 ## 测试策略 - 生命周期服务:启动成功、启动失败、重复启动、重复关闭、关闭释放代理。 - 应用架构:`WorkUtilsApplication` 在业务分派前启动,并在 `finally` 中关闭。 - API 页面:不存在代理复选框;成功和失败状态文案、颜色语义、Tooltip 与 accessible text 正确。 - 导出请求:三个模式不再接收或保存代理布尔值。 - 导出用例:成功时始终传递代理地址;失败时传递空地址且导出仍执行。 - 聚焦测试后运行 Maven 全量测试、编译和 `git diff --check`。 ## 验收标准 1. 启动 WorkUtils 后,无需打开 API 导出页面即可在日志中看到本地代理启动地址。 2. API 导出页没有代理复选框,仅显示已启动或失败状态。 3. 代理成功时,任何 API 导出都自动获得代理地址。 4. 代理失败时,WorkUtils 和普通文档导出仍可使用,页面清楚提示调试功能不可用。 5. WorkUtils 运行结束时代理端口和线程池被主动释放。