# mock-server **Repository Path**: artislong/mock-server ## Basic Information - **Project Name**: mock-server - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2021-05-25 - **Last Updated**: 2026-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Mock Server(多协议接口模拟服务) 一个轻量的 **多协议接口模拟服务**,用于在前端/联调阶段替代尚未开发完成或不易访问的后端接口。 基于 **Spring Boot 3 + WebFlux(响应式 Netty)**,数据持久化到 **嵌入式 H2 数据库**(文件模式,重启不丢数据)。 > 当前**没有独立的配置管理页面**,所有模拟接口的新增 / 删除 / 查询都通过 **Swagger UI**(OpenAPI 文档页)完成。详见下文「通过 Swagger 配置模拟接口」。 --- ## 一、支持的协议 | 协议 | 接入方式 | 状态 | 配置路径前缀 | 端点前缀 / 默认端口 | | --- | --- | --- | --- | --- | | **HTTP** / HTTPS | 普通 + 流式 | ✅ 已支持 | `HTTP` | `/index/{method}`、`/index/stream/{method}` | | **WebSocket** | 真 WS 客户端 | ✅ 已支持 | `WEBSOCKET` | `/ws/{method}` | | **MCP**(Model Context Protocol) | JSON-RPC 2.0 over HTTP | ✅ 已支持 | `MCP` | `/mcp/{method}` | | **Webhook** | 入站捕获(GET/POST)+ 出站触发 | ✅ 已支持 | `WEBHOOK` | `/webhook/{method}`、`/webhook/{method}/calls` | | **AI Agent Debugger** | JSON-RPC 2.0 over HTTP | ✅ 已支持 | `AI_AGENT` | `/ai/{method}` | | **A2A Debugger** | Google A2A JSON-RPC 2.0 over HTTP | ✅ 已支持 | `A2A` | `/a2a/{method}` | | **TCP (Socket)** | 裸 TCP(独立端口) | ✅ 已支持 | `TCP` | 默认 `9898` | | **Socket.IO** | netty-socketio(独立端口) | ✅ 已支持 | `SOCKET_IO` | 默认 `9876` | | **gRPC** | grpc-netty-shaded(独立端口) | ✅ 已支持 | `GRPC` | 默认 `9090` | | **Dubbo** | Apache Dubbo GenericService(独立端口) | ✅ 已支持 | `DUBBO` | 默认 `9099` | > 四种新协议均运行在**独立端口**上(不与主 HTTP 8989 冲突),启动日志会打印各端口监听情况。它们与 HTTP 等协议共享同一份 `mock_method` 表,按 `(protocol, request_method, method_name)` 查表返回 `data`。 > 所有协议共享同一个 H2 表 `mock_method`,业务主键 `(protocol, request_method, method_name)`,可在同一份 Swagger 配置里同时管理多种协议的端点。 --- ## 二、特性 - **HTTP 接口模拟**:任意 HTTP 方法(GET/POST/PUT/...)按「方法名」返回预设 JSON。 - **延迟模拟**:为接口配置固定延迟(毫秒),无需在业务侧 `sleep`。 - **SpEL 动态化**:在响应体中写 `#{...}` 表达式,可引用请求体 / 请求头,实现「同一接口按入参返回不同数据」。 - **SSE 流式模拟**:通过独立的 **流式端点** `/index/stream/{method}`,把 `data` 中 `streamField` 指定的字段按字符切片、以 `text/event-stream` 逐片推送给前端,模拟大模型 / 打字机效果。 - **WebSocket 模拟**:`/ws/{method}` 接受真 WS 连接,支持 `info.echo` 回声、`info.onConnect` 连接时推送。 - **MCP 模拟**:`/mcp/{method}` 完整实现 JSON-RPC 2.0:initialize / tools/list / tools/call / resources/list / resources/read / prompts/list / prompts/get / ping。 - **AI Agent Debugger 模拟**:`/ai/{method}` JSON-RPC 2.0:initialize / agents/list / agents/invoke / sessions/list / sessions/get / ping,用于在没有真实 Agent 运行时的情况下调试「AI Agent 调试服务」。 - **A2A Debugger 模拟**:`/a2a/{method}` JSON-RPC 2.0(Google Agent-to-Agent Protocol):agentCard / tasks/send / tasks/get / tasks/cancel / ping,用于调试 Agent 间任务协作。 - **Webhook 模拟**:`/webhook/{method}` 入站捕获外部系统发来的回调(方法 / 路径 / Query / Header / Body 全部存档,可经 `GET /webhook/{method}/calls` 回看);任意协议的方法都可在 `info.webhook` 配置出站回调 URL,被调用时自动以 POST 推送请求上下文。 - **多协议共存**:同一方法名可在不同协议下独立配置(如 `HTTP /test` 与 `WEBSOCKET /test` 互不影响)。 - **历史快照**:覆盖写接口定义时自动保留旧版本,可随时查看 / 删除历史。 - **持久化**:H2 文件库,库文件位于启动目录下 `mockdb.mv.db`,服务重启数据不丢失。 --- ## 三、环境要求 | 依赖 | 版本 | 说明 | | --- | --- | --- | | JDK | **17 或 21** | ⚠️ 不要用 **JDK 25**:本项目配套的 Lombok 暂不支持 JDK 25,会在编译期报 `log` / `setXxx` 等方法找不到。 | | Maven | 3.9+ | 用于构建与运行 | | 操作系统 | Windows / Linux / macOS | 无特殊依赖 | --- ## 四、配置(application.yml) 配置文件位于 `src/main/resources/application.yml`,可按需修改: ```yaml server: port: 8989 # 服务端口,按需修改 spring: r2dbc: url: r2dbc:h2:file:///./mockdb # H2 文件库;./mockdb 表示库文件落在「启动目录」下 username: sa password: '' sql: init: mode: always # 启动时执行 schema.sql 自动建表(mock_method / mock_history) springdoc: # Swagger / OpenAPI 文档配置(WebFlux 原生) swagger-ui: path: /swagger-ui.html api-docs: path: /v3/api-docs ``` 常用调整点: - **改端口**:修改 `server.port`。 - **换库位置**:`r2dbc:h2:file:///D:/data/mockdb` 可指定绝对路径。 - **跨域**:已默认允许所有来源(`CorsWebFilter`,见 `WebServerConfiguration`),如要收紧可改该配置类。 --- ## 四、启动 ### 方式一:Maven 直接运行 ```bash # 注意:先确保 JAVA_HOME 指向 JDK 17/21,不要用 JDK 25 export JAVA_HOME=/path/to/jdk-17 mvn -f pom.xml spring-boot:run ``` > 在 Windows 上若遇到 Maven 脚本异常,建议用 `mvn.cmd` 并在 PowerShell 中执行: > ```powershell > $env:JAVA_HOME = "D:\path\to\jdk-17" > mvn.cmd -f pom.xml spring-boot:run > ``` ### 方式二:打成 jar 运行 ```bash mvn -f pom.xml clean package java -jar target/mock-server-*.jar ``` > ⚠️ 若要用到 **Dubbo** 协议(Phase 4),JDK 17 下必须带 `--add-opens` 启动(见 FAQ)。 > 仓库已提供封装好参数的启动脚本,直接运行即可: > ```bash > # Windows > bin\start.cmd > # Linux / macOS / Git Bash > bash bin/start.sh > ``` 启动成功后,控制台会输出 Netty 监听在 `8989` 端口,以及各协议独立端口(TCP 9898 / Socket.IO 9876 / gRPC 9090 / Dubbo 9099)的监听日志。 ### 验证是否启动成功 打开浏览器访问 **Swagger UI**: ``` http://localhost:8989/swagger-ui.html ``` 能看到 `index`、`历史记录` 两个分组即表示启动正常。 --- ## 五、通过 Swagger 配置模拟接口 > 本项目暂无独立配置页面,所有接口定义的新增 / 删除 / 查询都通过 Swagger UI 完成。 ### 1. 打开配置页 浏览器访问 `http://localhost:8989/swagger-ui.html`,展开 **index** 分组,你将看到以下管理接口: | 接口 | 方法 | 说明 | | --- | --- | --- | | `/index/addMethod/{requestMethod}/{method}` | PUT | **新增 / 覆盖写**一个模拟接口(核心) | | `/index/deleteMethod/{requestMethod}/{method}` | DELETE | 删除一个模拟接口 | | `/index/db` | GET | 查看某个接口定义,或查看全部接口 | | `/index/allMethods` | GET | 查看全部接口名(按 HTTP 方法分组) | ### 2. 新增一个模拟接口(核心步骤) 1. 在 Swagger UI 中找到 `PUT /index/addMethod/{requestMethod}/{method}`,点击 **Try it out**。 2. 填写路径参数: - `requestMethod`:接口使用的 HTTP 方法,如 `GET`、`POST`(**大写**)。 - `method`:接口名(自定义,作为访问路径的一部分),如 `getUser`。 3. 在 **Request body** 中填写接口定义 JSON: ```json { "data": { "code": 0, "message": "success", "data": { "id": 1, "name": "张三" } }, "info": { } } ``` - `data`:接口被访问时返回的**响应体**(任意 JSON)。 - `info`:可选配置(延迟 / SpEL / 流式),详见下一节。 4. 点击 **Execute**。返回 `OK` 即配置成功。 > 再次用相同 `requestMethod` + `method` 调用 `addMethod` 会**覆盖写**,且覆盖前的旧定义会自动存入历史。 ### 3. `info` 配置项详解 | 字段 | 类型 | 作用 | | --- | --- | --- | | `delay_time` | number(ms) | 返回前延迟的毫秒数,用于模拟慢接口 | | `spel` | boolean | 设为 `true` 时,把 `data` 当作 SpEL 模板渲染(见下) | | `streamField` | string | 指定 `data` 中需要「切片流式」返回的字段名。**仅在流式端点 `/index/stream/{method}` 生效**,普通端点不受影响 | | `streamStep` | number | 流式时每次切片的长度(字符数),默认 2 | #### 示例 A:基础接口(无 info) ```json { "data": { "code": 0, "list": [1, 2, 3] } } ``` #### 示例 B:带延迟的接口 ```json { "data": { "code": 0, "message": "slow response" }, "info": { "delay_time": 3000 } } ``` 访问该接口会**延迟 3 秒**再返回。 #### 示例 C:SpEL 动态化(按入参返回不同数据) 令 `info.spel = true`,`data` 中的 `#{...}` 会被渲染。可用变量: - `#{REQ_BODY.xxx}` —— 引用请求 **JSON 体** 的字段 - `#{HEADER.xxx}` —— 引用请求 **头** - `#{URL_PARAM}` —— 原始查询字符串 - 根对象还内置 `SYSTEM_USER_NAME` 等系统变量 - 已注册自定义函数 `#{transCode(code, '0=正常&1=失败')}` 配置示例: ```json { "data": { "code": 0, "user": { "name": "#{REQ_BODY['name']}", "nameUpper": "#{REQ_BODY['name'].toUpperCase()}" } }, "info": { "spel": true } } ``` 访问 `POST /index/echo` 且请求体为 `{"name":"tom"}` 时,返回: ```json { "code": 0, "user": { "name": "tom", "nameUpper": "TOM" } } ``` #### 示例 D:SSE 流式接口(模拟打字机 / 大模型输出) 令 `info.streamField` 指向 `data` 中一段长文本字段。配置后通过独立的 **流式端点** `/index/stream/{method}` 访问,该字段会被按 `streamStep` 字符切片、以 `text/event-stream` 逐片推送。 ```json { "data": { "content": "这是一段需要逐字流式返回的模拟文本,用来演示 SSE 效果。", "model": "mock-llm" }, "info": { "streamField": "content", "streamStep": 3 } } ``` - **普通端点** `GET /index/chat` 始终**原样返回整个 `data` 对象**,不做切片 —— 流式已拆分到专门端点(见下节)。 - **流式端点** `GET /index/stream/chat`(HTTP 方法同样须与 `requestMethod` 一致)才会按 `streamField` 切片、以 SSE 持续推送。 - 若未配置 `streamField` 就访问流式端点,则把整个 `data` 作为单个 SSE 分片一次性返回。 > 流式推送的分片对象结构为 `{ "id", "model", "choices": [ { "content": "...", "finish_reason": "stop" } ] }`,与常见 LLM 流式响应结构一致。 --- ## 六、访问模拟接口 所有模拟接口统一通过 `/index/{method}` 访问,HTTP 方法须与配置时填写的 `requestMethod` 一致。 ### 0. 调试中心页面(内置 Web UI,无需前后端分离) 启动后直接访问根路径即可打开「多协议调试中心」单页: ``` http://localhost:8989/ ``` 页面为**纯 HTML / CSS / JavaScript**(同源、不分离、不依赖 Vue 等前端框架),由 `src/main/resources/static/` 下的 `index.html` / `style.css` / `app.js` 提供,后端通过 `PageController` 在 `/` 直接以 `text/html` 返回。功能面板: - **接口管理(数据表格 CRUD)**:顶部「查询条件」(协议 / 请求方法 / 接口名模糊)点击「查询」调用 `GET /index/db` 拉取并渲染表格;支持**全选 / 单选**、**批量删除**与**单个删除**(均弹确认框,确认后才调 `DELETE /index/deleteMethod/...`);「+ 新增接口」弹窗填写 `protocol / requestMethod / methodName / data / info` 后保存(`PUT /index/addMethod/...`);「修改」弹窗回显 `data/info` 并覆盖更新;每行「测试」弹窗按协议真实调用该接口以验证(HTTP 发请求、Webhook GET/POST、WebSocket 连接、JSON-RPC 选方法发请求)。 - **HTTP 调用**:直接打 `/index/{method}` 并查看响应。 - **SSE 流式**:`EventSource` 连接 `/index/stream/{method}`,实时显示事件流。 - **WebSocket**:连接 `ws://host/ws/{method}`,收发帧。 - **JSON-RPC**:针对 MCP / AI Agent / A2A,发送 JSON-RPC 2.0 请求到 `/mcp`、`/ai`、`/a2a` 并查看响应(内置各方法默认请求体)。 - **Webhook 捕获**:查看 / 清空入站归档(`GET|DELETE /webhook/{method}/calls`)。 - **历史记录**:查看 / 清空某接口的历史快照(`/history/...`)。 ### 1. 普通 JSON 接口(原样返回 `data`) ```bash # 配置时 requestMethod=GET, method=getUser curl http://localhost:8989/index/getUser # 配置时 requestMethod=POST, method=echo(带 SpEL) curl -X POST http://localhost:8989/index/echo \ -H "Content-Type: application/json" \ -d '{"name":"tom"}' ``` 响应**就是你配置的 `data` 对象本身**(SpEL 已渲染、延迟已生效),不会被任何包装或转成字符串。例如配置 `data` 为 `{ "code": 0, "message": "success", "data": { "id": 1, "name": "张三" } }`, 调用后返回的就是这段 JSON,而不是被包成 `[ "..." ]` 或 `"..."`。 ### 2. SSE 流式接口(独立端点) 流式已与上面的普通端点**拆分开**,单独走 `/index/stream/{method}`。HTTP 方法同样须与 `requestMethod` 一致,且 `info.streamField` 必须配置: ```bash # 配置时 requestMethod=GET(或 POST,保持一致),method=chat curl -N http://localhost:8989/index/stream/chat ``` `-N` 关闭 curl 缓冲,可看到服务端逐片推送的 SSE 数据(分片结构见示例 D)。 ### 3. 接口不存在时 若访问的 `method` 未配置,返回字符串 `No Data`(HTTP 200)。 > 普通端点路径精确匹配 `/index/{method}`(不带额外通配子路径)。如需演示流式但不想先配置,可直接用内置演示接口 `GET /index/stream` 与 `GET /index/stream-loop`。 --- ## 六-B、新增协议:Webhook / AI Agent Debugger / A2A Debugger(Phase 2) 三种协议均复用同一份 `mock_method` 表与 Swagger 配置入口,区别只在 `protocol` 字段与端点前缀。 ### 1. AI Agent Debugger(`/ai/{method}`,JSON-RPC 2.0) 把 `{method}` 当作一个「AI Agent 调试服务」名。配置示例(`PUT /index/addMethod/AI_AGENT/POST/demo`): ```json { "data": {}, "info": { "serverInfo": { "name": "mock-ai-agent", "version": "1.0" }, "capabilities": { "agents": {}, "sessions": {} }, "agents": [ { "name": "summarizer", "description": "摘要", "response": { "summary": "..." } } ], "sessions": [ { "id": "s1", "agent": "summarizer", "messages": [ ... ] } ] } } ``` 支持的 JSON-RPC 方法:`initialize` / `agents/list` / `agents/invoke` / `sessions/list` / `sessions/get` / `ping`。调用示例: ```bash curl -X POST http://localhost:8989/ai/demo \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"agents/invoke","params":{"name":"summarizer"}}' ``` ### 2. A2A Debugger(`/a2a/{method}`,JSON-RPC 2.0) 把 `{method}` 当作一个 A2A 服务名。配置示例(`PUT /index/addMethod/A2A/POST/demo`): ```json { "data": {}, "info": { "agentCard": { "name": "mock-a2a-agent", "description": "demo", "url": "http://localhost:8989/a2a/demo", "capabilities": { "streaming": false }, "skills": [ { "id": "translate" } ] }, "tasks": [ { "id": "t1", "sessionId": "s1", "status": "completed", "artifacts": [ { "name": "out.txt", "parts": [ { "text": "hi" } ] } ] } ] } } ``` 支持的 JSON-RPC 方法:`agentCard` / `tasks/send` / `tasks/get` / `tasks/cancel` / `tasks/sendSubscribe`(流式,mock 暂不支持,返回 -32601)/ `ping`。 ### 3. Webhook(入站捕获 + 出站触发) - **入站**:`POST` / `GET /webhook/{method}` 捕获外部系统发来的回调(方法、路径、Query、Header、Body 全部存档),并返回你为该 `method` 配置的 `data`(未配置则返回 `{"ok":true}`)。 - **查看存档**:`GET /webhook/{method}/calls`;**清空**:`DELETE /webhook/{method}/calls`。 - **出站**:任意协议的方法都可在 `info` 里加 `"webhook": "http://目标URL"`,被调用时自动以 POST 把请求上下文(或 `info.webhookBody` 覆盖)推送到该 URL。示例(`PUT /index/addMethod/HTTP/POST/hookme`): ```json { "data": { "done": true }, "info": { "webhook": "http://localhost:8989/webhook/cb" } } ``` 调用 `POST /index/hookme` 后,访问 `GET /webhook/cb/calls` 即可看到这次出站触发的入站归档。 --- ## 六-C、新增协议:TCP / Socket.IO / gRPC / Dubbo(Phase 3 / 4) 四种协议均运行在**独立端口**(与主 HTTP 8989 互不干扰),并复用同一份 `mock_method` 表。 由于它们不是「HTTP 方法 + 路径」模型,配置时的 `requestMethod` 使用**占位标签**来占位: | 协议 | 占位 requestMethod | method_name 取什么 | 默认端口 | | --- | --- | --- | --- | | TCP | `TCP` | 客户端发送的**首行文本** | 9898 | | Socket.IO | `SOCKETIO` | 连接 URL 的 **`?method=`** 参数 | 9876 | | gRPC | gRPC 方法名(如 `SayHello`) | 服务名 `mock.MockService` | 9090 | | Dubbo | Dubbo 方法名(如 `sayHello`) | 接口名 `com.github.mock.MockGenericService` | 9099 | 端口可在 `application.yml` 的 `mock.*.port` 调整(见上文「四、配置」);设为 `0` 表示使用系统临时端口。 ### 1. TCP(裸 TCP,行协议) 客户端连上后**按行**通信:服务端把首行(去换行与首尾空白)当作方法名去查表;命中返回配置的 `data`,未命中原样回声。连接保持,可连续多行请求。 ```bash # 1) 配置:protocol=TCP, requestMethod=TCP, method=echo curl -X PUT "http://localhost:8989/index/addMethod/TCP/TCP/echo" \ -H "Content-Type: application/json" \ -d '{"data":{"tcp":"hello"}}' # 2) 测试(首行发 "echo",服务端回 data) printf 'echo\n' | nc localhost 9898 # -> {"tcp":"hello"} ``` ### 2. Socket.IO(netty-socketio) 客户端连接时通过 `?method=<方法名>` 指定要匹配的接口;连接建立后服务端通过 `data` 事件下发配置的响应(客户端主动发 `message` 也会触发同样的回写)。 ```bash # 1) 配置:protocol=SOCKET_IO, requestMethod=SOCKETIO, method=chat curl -X PUT "http://localhost:8989/index/addMethod/SOCKET_IO/SOCKETIO/chat" \ -H "Content-Type: application/json" \ -d '{"data":{"msg":"hi"}}' # 2) 测试:浏览器/Node 用官方 socket.io-client 连接 http://localhost:9876/?method=chat # 连接成功后会收到 data 事件,payload 即 {"msg":"hi"}。 # (注:本仓库依赖的 netty-socketio 1.7.18 与 socket.io-client 2.x 握手帧存在兼容性差异, # 若使用 2.x 客户端握手失败,可改用 engine.io v3 polling 直接访问 # http://localhost:9876/socket.io/?EIO=3&transport=polling&method=chat ) ``` ### 3. gRPC(grpc-netty-shaded,通用 Invoke 免 protoc) 服务名固定 `mock.MockService`、方法固定 `Invoke`,请求体为 JSON: ```json { "method": "", "service": "mock.MockService", "payload": { } } ``` 响应即配置中的 `data`(JSON 文本,pass-through 字节透传,无需 protobuf 编解码)。随包附带 `src/main/resources/proto/mock.proto` 供客户端生成 stub。 ```bash # 1) 配置:protocol=GRPC, requestMethod=SayHello, method=mock.MockService curl -X PUT "http://localhost:8989/index/addMethod/GRPC/SayHello/mock.MockService" \ -H "Content-Type: application/json" \ -d '{"data":{"grpc":"ok"}}' # 2) 测试:用 grpcurl 调通用 Invoke(需先有 mock.proto) grpcurl -plaintext -d '{"method":"SayHello","service":"mock.MockService","payload":{}}' \ localhost:9090 mock.MockService/Invoke # -> {"grpc":"ok"} ``` ### 4. Dubbo(Apache Dubbo GenericService,免接口类) 服务端以通用服务方式导出接口 `com.github.mock.MockGenericService`(无需定义 Java 接口),客户端用 generic 调用 `$invoke(<方法名>, ...)`。 ```bash # 1) 配置:protocol=DUBBO, requestMethod=sayHello, method=com.github.mock.MockGenericService curl -X PUT "http://localhost:8989/index/addMethod/DUBBO/sayHello/com.github.mock.MockGenericService" \ -H "Content-Type: application/json" \ -d '{"data":{"dubbo":"ok"}}' # 2) 测试:Java 侧用 GenericService 直连端口 9099 调用 # reference.setInterface("com.github.mock.MockGenericService"); # reference.setGeneric("true"); # reference.setUrl("dubbo://127.0.0.1:9099/com.github.mock.MockGenericService?generic=true"); # genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"world"}); # -> 返回 {"dubbo":"ok"} ``` > ⚠️ **JDK 17 必读(仅 Dubbo)**:Dubbo 的 Hessian2 序列化在 JDK 17 下需要反射 JDK 内部类, > 必须在启动 JVM 加 `--add-opens`(见下文「九、常见问题」Q:Dubbo 启动报 InaccessibleObjectException)。 > 仓库已内置 `bin/start.sh` / `bin/start.cmd` 与 `.mvn/jvm.config`,按下面「四、启动」的脚本启动即可。 --- ## 七、历史记录管理 每次覆盖写接口定义时,旧版本会自动存入历史快照。相关接口(Swagger UI 的 **历史记录** 分组): | 接口 | 方法 | 说明 | | --- | --- | --- | | `/history/history/{requestMethod}/{method}` | GET | 查看某接口的全部历史快照 | | `/history/history/{requestMethod}/{method}` | DELETE | 删除某接口的历史 | | `/history/clearAll` | DELETE | 清空全部历史 | --- ## 八、内置演示接口(与配置无关) `IndexController` 自带两个 SSE 演示接口,方便直接体验流式效果(无需先配置): - `GET /index/stream` —— 推送若干预设事件后结束。 - `GET /index/stream-loop` —— 循环持续推送预设事件。 --- ## 九、常见问题 **Q:启动时报 `javax.servlet.Filter` / `NoClassDefFoundError`?** A:本项目是 WebFlux(无 Servlet 容器),请勿引入基于 Servlet 的 knife4j(springfox 系)等依赖。文档能力已用 `springdoc-openapi-starter-webflux-ui` 替代。 **Q:编译报 `log` / `setXxx` 找不到?** A:Lombok 与 JDK 25 不兼容。请把 `JAVA_HOME` 切换到 **JDK 17 或 21** 再构建。 **Q:数据存在哪里?** A:H2 文件库,默认 `mockdb.mv.db`,位于**启动目录**(即你执行启动命令时的当前目录)。换目录启动即使用新的空库。 **Q:如何查看已配置的全部接口?** A:Swagger UI 调用 `GET /index/allMethods`,或直接访问 `http://localhost:8989/index/allMethods`。 **Q:Dubbo 启动报 `InaccessibleObjectException: Unable to make ... java.math.BigInteger ... accessible`?** A:这是 **JDK 17 模块封装**限制——Dubbo 的 Hessian2 序列化需在运行时反射 `java.math` / `java.lang` 等 JDK 内部类。两种解决方式(任选其一): 1. 用仓库自带脚本启动(已含参数):`bash bin/start.sh`(Linux/macOS/Git Bash)或 `bin\start.cmd`(Windows);`mvn spring-boot:run` 会自动读取 `.mvn/jvm.config` 注入同样参数。 2. 手动在 JVM 加 `--add-opens`: ```bash java --add-opens java.base/java.lang=ALL-UNNAMED \ --add-opens java.base/java.lang.reflect=ALL-UNNAMED \ --add-opens java.base/java.lang.invoke=ALL-UNNAMED \ --add-opens java.base/java.math=ALL-UNNAMED \ --add-opens java.base/java.util=ALL-UNNAMED \ --add-opens java.base/java.util.concurrent=ALL-UNNAMED \ --add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED \ -jar target/mock-server-*.jar ``` > 该要求**仅影响 Dubbo 协议**;TCP / Socket.IO / gRPC 在 JDK 17 下无需额外参数。 **Q:TCP / Socket.IO / gRPC / Dubbo 的接口怎么配置?** A:它们与 HTTP 共用 `mock_method` 表,但 `requestMethod` 用占位标签(TCP→`TCP`、Socket.IO→`SOCKETIO`、gRPC→方法名、Dubbo→方法名)。详见上文「六-C」各协议示例。 --- ## 十、项目结构(简要) ``` com.github ├── MockServer.java # 启动类 ├── config │ └── WebServerConfiguration # CORS 等 WebFlux 配置 ├── controller │ ├── IndexController # 模拟接口访问 + 接口管理(add/delete/db/allMethods)+ SSE 演示 │ ├── HistoryController # 历史记录管理 │ ├── McpController # MCP 协议:JSON-RPC 2.0 over HTTP(/mcp) │ ├── AiAgentController # AI Agent Debugger:JSON-RPC 2.0 over HTTP(/ai) │ ├── A2aController # A2A Debugger:JSON-RPC 2.0 over HTTP(/a2a) │ ├── WebhookController # Webhook 入站捕获 + 存档查看(/webhook) │ ├── PageController # 调试中心页面入口(/ → static/index.html) │ └── JsonRpcSupport # JSON-RPC 2.0 解析/结果/分发共享支撑 ├── service │ ├── MockService # mock 解析:普通端点原样返回(延迟 / SpEL / 出站 webhook);流式端点 SSE 分片 │ ├── MockRequest / MockResolution │ ├── WebhookService # 出站 webhook 触发(WebClient + boundedElastic) │ └── MockStore # H2 存储层(R2DBC 响应式) ├── handler │ └── MockWebSocketHandler # WebSocket 协议处理 ├── entity │ ├── MockMethod # 接口定义表 │ ├── MockHistory # 历史快照表 │ └── WebhookCapture # 入站 webhook 归档(内存) ├── store │ ├── MockMethodRepository ... # R2dbcRepository │ └── WebhookCaptureStore # 入站 webhook 内存归档 ├── protocol │ ├── MockProtocol # 协议枚举(HTTP/WEBSOCKET/WEBHOOK/MCP/AI_AGENT/A2A/TCP/SOCKET_IO/GRPC/DUBBO) │ ├── MockResolver # 解析接口:按 (protocol, requestMethod, methodName) 取 data │ └── DbMockResolver # 基于 H2 的实现(boundedElastic 上阻塞取值,兼容非 HTTP 线程) ├── server # 非 HTTP 协议服务(各自独立端口) │ ├── TcpMockServer # 裸 TCP(行协议,9898) │ ├── SocketIoMockServer # netty-socketio(9876,?method= 指定接口) │ ├── GrpcMockServer # grpc-netty-shaded 通用 Invoke(9090,mock.MockService/Invoke) │ └── DubboMockServer # Apache Dubbo GenericService(9099,com.github.mock.MockGenericService) ├── config │ ├── WebServerConfiguration # CORS 等 WebFlux 配置 │ ├── MockServerProperties # 非 HTTP 协议端口配置(mock.*.port) │ └── MockProtocolServersConfig # 装配并统一启动/停止四个协议服务 └── core.parse ├── spel # SpEL 渲染引擎 └── sse # SSE / LLM 分片解析 ```