17 KiB
下游接口明细改造方案:小改 vs 大改
场景:下游接口页(
/api/downstreamInterface)保存接口明细时,需要更好支持 FormUrlEncoded / 表单类接口 中「某个字段的值是一整段 JSON」的情况。
目标:为上游映射提供独立的 Mapping Body(映射体) 结构树,表单字段用$FromMappingBody引用映射结果。
参考 UI:/api/apiDebugger(ApiTest:Query / Request(Body) / Header)。
1. 现状速览(为何需要改)
| 层级 | 现状 | 问题 |
|---|---|---|
| 表 | t_parameter(IsInPara)= 入参树;t_parameter_form(无位置)= 表单 KV;t_parameter_fixed(FieldPositions)= 固定 Header/Query/Body |
前端「Query」Tab 实际写的是 formParameterList,后端却只把 Form 当 整段 x-www-form-urlencoded Body,不是 URL Query |
| 页面 | InterfaceDetail:Query(表单) + Body(参数树) + 固定配置 + cURL | 与 ApiTest 的 Query/Body/Header 不一致;Body 树同时承担「HTTP JSON 结构」和「上游映射主体」,表单里 JSON 字段只能塞 $FromBody,语义混 |
| 转发 | InParamRestructure ← 下游 IsInPara 树;FormFieldList ← 全部 form;Query/Header ← FixedFieldList |
映射树与传输层表单未分离 |
上游 JSON ──► InParamRestructure(下游 IsInPara 树) ──► OriginalInterfaceMappedInput
│
▼
ReplacePlaceholder / 序列化
│
▼
FormUrlEncoded(form 全进 Body)+ Fixed(Query/Header)
2. 方案总览
| 维度 | 方案 A:小改(推荐优先) | 方案 B:大改(完全对齐 ApiTest) |
|---|---|---|
| 核心思路 | 只新增 Mapping Body 参数树 + $FromMappingBody,其余结构基本不动 |
Query/Body/Header 表单分表存储 + 转发按位置组装;Mapping Body 独立;逐步弱化「固定配置」与旧 form 语义 |
| 表变更 | 1 张表加 1 个字段(或 1 个枚举列) | 至少 2 张表扩展 + 数据迁移 + 行为重构 |
| API 变更 | SaveInterface / GetInterfaceById 增字段;占位符枚举增 1 项 |
契约重组(多列表/统一带 position);Fixed 与 Form 职责重划 |
| 转发逻辑 | 映射树数据源切换 + 占位符分支(约数十行级) | RequestAsync / SetContentType / 缓存 / 映射 SQL 全链路调整 |
| 前端 | InterfaceDetail 增 1 个 Tab,保存多传一个列表 | 整页 Request 区重写,对齐 ApiTest;curl 填充、映射页联动 |
| 风险 | 低,可灰度、可回滚 | 中高,影响所有下游接口与发布数据 |
| 工期(粗估) | 后端 2~4 人日 + 前端 3~5 人日 | 后端 8~15 人日 + 前端 10~18 人日 + 联调/迁移 |
3. 方案 A:小改(Mapping Body 增量)
3.1 要解决什么
只解决:Query/Body 表单里某字段值为 JSON(或应填 $FromBody)时,上游映射应对的是 JSON 内部结构,而不是把整段 form 或错误树当映射目标。
不解决(保持现状):
- Form 仍整体作为
FormUrlEncodedBody(不拆真正的 URL Query 表单 Tab 行为) - Header 仍主要走 固定配置(
FixedParameter) ContentType=Json的下游接口仍用现有inParameterList作 Body + 映射(可不显示 Mapping Body Tab)
3.2 表结构
| 表 | 变更 | 说明 |
|---|---|---|
t_parameter |
新增 ParaKind(int)或 IsMappingBody(bit) |
0=Normal(现有入参/出参逻辑),1=MappingBody(仅映射,不参与 Json 序列化 Body 时可配置策略) |
t_parameter_form |
不改 | 仍 flat KV;JSON 字段 value 改为 $FromMappingBody |
t_parameter_fixed |
不改 | Header/Query 固定值照旧 |
迁移:历史数据 ParaKind=0;原 inParameterList 若实为映射树,可脚本把「仅用于 FormUrlEncoded 映射」的接口标为 MappingBody,或 读时兼容(见下)。
3.3 接口契约
GET Interface/GetInterfaceById
{
"inParameterList": [],
"mappingBodyParameterList": [],
"formParameterList": [],
"outParameterList": []
}
兼容规则:
- 若
mappingBodyParameterList为空 → 用inParameterList填充(老数据零感知) - 新保存的 FormUrlEncoded 接口:映射树写
mappingBodyParameterList,inParameterList可留空或仅存「真实 HTTP JSON Body 结构」(Json 类型仍用 in)
POST Interface/SaveInterface
{
"mappingBodyParameterList": [{ "optionType": 1, "id": 1, "pId": 0, "name": "order", "alias": "order", "type": 3 }],
"inParameterList": [],
"formParameterList": [
{ "name": "notifyBizEventDTO", "value": "$FromMappingBody", "optionType": 0 }
]
}
inParameterList / outParameterList / formParameterList 字段 保留,老前端、导入导出可继续用。
其它接口
| 接口 | 变更 |
|---|---|
Dictionary/GetList?type=ParameterPlaceholder |
后端枚举加 FromMappingBody → 展示 $FromMappingBody |
InterfaceMap/*(映射编辑) |
下游入参映射 SQL/列表 优先 ParaKind=MappingBody,无则回退 IsInPara |
FixedParameter/* |
无 |
FormParameter/GetParameterList |
无 |
3.4 后端逻辑改动点
| 模块 | 改动量 | 内容 |
|---|---|---|
ParameterService / InterfaceService |
小 | 保存/读取时按 ParaKind 过滤;维护 MappingBody 列表 |
InterfaceForwardQuery.GetParameterMapListAsync |
小 | JOIN t_parameter 增加 ParaKind=MappingBody 条件(入参映射) |
InterfaceForwardQuery 构建 InParamTreeList |
小 | 有 MappingBody 用其建树,否则用原 IsInPara |
DefaultForwardFlow.ReplacePlaceholder |
小 | FixedFieldList / FormFieldList 增加 $FromMappingBody → Serialize(OriginalInterfaceMappedInput) |
DefaultForwardFlow.SetContentType |
小 | FormUrlEncoded 里对 $FromMappingBody 与 $FromBody 同样替换为序列化结果(可共用实现) |
DefaultForwardFlow.RequestAsync |
无或极小 | 不拆 Query/Header 表单 |
ServiceProviderImportExportService |
小 | 导出/导入带上 ParaKind |
发布缓存 ForwardCoreContextCache |
小 | 缓存参数列表带 ParaKind |
$FromBody vs $FromMappingBody(小改语义建议)
| 占位符 | 小改建议语义 |
|---|---|
$FromBody |
保持现有行为(兼容老配置) |
$FromMappingBody |
明确指向 OriginalInterfaceMappedInput 的序列化(映射完成后、写进 form 字段) |
3.5 前端改动点
| 文件/模块 | 改动量 |
|---|---|
InterfaceDetail |
中:Request 区增加 Mapping Body Tab(复用现有 Body 树表格);原 Body Tab 可改名为「传输 Body」或保留树仅给 Json 类型显示 |
ServiceProviderInterfaceModal.saveInterface |
小:多组装 mappingBodyParameterList;formParameterList 仍只来自 Query 表 |
curlToInterfaceFill |
小:JSON 类 form 字段推断 $FromMappingBody |
upstreamInterfaceConfig 映射页 |
小:下游参数源改读 mapping 列表(后端改即可) |
itfxEnums / 文档 |
小 |
ApiTest |
无 |
3.6 方案 A 优点 / 缺点
优点
- 改动面可控,只增加概念,不推翻 Form/Fixed 分工
- 老接口、老映射、老占位符可继续跑
- 符合「多的映射 body 只解决表单里还有 json」的诉求
缺点
- UI 仍与 ApiTest 不完全一致(Query 名不副实、Header 仍在固定配置)
- 技术债仍在:
formParameterList≠ URL Query
4. 方案 B:大改(完全对齐 API 调试)
4.1 目标结构(与 ApiTest 一致)
┌─ 基本信息(地址、Method、ContentType…)────────────────┐
├─ Query KV 表 → 真实 URL Query │
├─ Body KV 表 → Form Body / 或 Raw(按 ContentType) │
├─ Header KV 表 → 请求头 │
├─ Mapping Body 参数树 → 仅上游映射主体($FromMappingBody) │
├─ Response 参数树 + 返回配置(保持) │
└─ cURL 示例(可选) ┘
传输层(Query/Body/Header)与映射层(Mapping Body)彻底分离。
4.2 表结构
| 表 | 变更 | 说明 |
|---|---|---|
t_parameter_form |
新增 FieldPosition(int,enum:Header=1, Body=2, Query=3) |
一条 form 记录明确归属;历史数据默认 Body=2 |
t_parameter |
新增 ParaKind(Normal / MappingBody / 可选 TransportBody) |
MappingBody 只用于映射;Json 接口的 HTTP Body 树可用 Normal 或单独 Kind |
t_parameter_fixed |
可选废弃或降级 | Header/Query 迁入 form 后,Fixed 仅保留服务商级 / Url 路径 / 脚本写入项;需迁移工具 |
t_interface |
一般不改 | — |
数据迁移
- 旧
formParameterList→FieldPosition=Body - 旧
inParameterList(Form 场景)→ 拆到MappingBody+ 清空 in 或保留 Json 专用 - 旧
FixedParameter(Header/Query)→ 迁入t_parameter_form或双写过渡期
4.3 接口契约(重组)
GetInterfaceById(示例)
{
"queryFormParameterList": [],
"bodyFormParameterList": [],
"headerFormParameterList": [],
"mappingBodyParameterList": [],
"inParameterList": [],
"outParameterList": [],
"formParameterList": []
}
formParameterList 兼容期 = 三表合并;新前端只认分列表。
SaveInterface
- 必传:
queryFormParameterList+bodyFormParameterList+headerFormParameterList+mappingBodyParameterList+outParameterList inParameterList:仅 ContentType=Json 时作为 HTTP JSON Schema(或合并进 mapping,产品需二选一)
其它
| 能力 | 大改影响 |
|---|---|
FixedParameter/MaintainParameter |
接口明细页可能 移除 或仅服务商维度保留 |
授权 ServiceProviderAuth |
入参列表来源可能改为 MappingBody |
| 接口映射发布/对比 | 参数树 diff 逻辑调整 |
| 导入导出 | 全量适配 position + ParaKind |
| 前置脚本 Skill | FormFieldList 分 position;文档重写 |
4.4 后端逻辑改动点
| 模块 | 改动量 | 内容 |
|---|---|---|
FormParameterService |
大 | CRUD 带 FieldPosition;按 position 查询 |
InterfaceService Save/Get |
大 | 多列表合并/拆分 |
DefaultForwardFlow.RequestAsync |
大 | FormFieldList 按 Query → UriBuilder.Query;Header → msg.Headers;Body → SetContentType |
DefaultForwardFlow 与 Fixed 合并 |
大 | 同名冲突策略、服务商级覆盖规则 |
InterfaceForwardQuery |
大 | 映射、授权、缓存多处 |
InterfaceMapRepository SQL |
中 | 下游参数过滤 MappingBody |
ServiceProviderImportExportService |
大 | |
| 单元/集成测试 | 大 | 需覆盖 Json / FormUrlEncoded / 混合 Header |
4.5 前端改动点
| 模块 | 改动量 |
|---|---|
InterfaceDetail |
很大:Request 区 Tabs 与 ApiTest 同构;删除或隐藏「固定配置」;三份 KV 表 + Mapping Body 树 |
ServiceProviderInterfaceModal |
大:保存/加载拆 4 类参数 |
ApiTest |
中:可抽公共组件 RequestTabs 复用 |
curlToInterfaceFill |
大:-H→header,?query→query,--data→body form 或 mapping |
downstreamInterface/index |
中 |
upstreamInterface |
小~中:上游是否展示 Mapping Body |
newPort.vue 等历史页 |
中:废弃或同步 |
4.6 方案 B 优点 / 缺点
优点
- 产品、开发、运维认知与 API 调试 一致,培训成本低
- Query/Header 行为正确,不再名不副实
- 映射与传输分层清晰,后续扩展 FormData、Raw Body 更自然
缺点
- 改动面大:表 + 转发 + 映射 + 导入导出 + 多页面
- 必须做 数据迁移与发布回归,线上 Form 接口需逐个验证
- 与「只为表单 JSON 加一个映射体」相比,投入不成比例(若 80% 接口是 Json Body)
5. 改动量对照(文件级清单)
5.1 后端 itfx-master(约)
| 路径/模块 | 方案 A | 方案 B |
|---|---|---|
ParameterEntity + 迁移 SQL |
● | ●● |
FormParameterEntity + 迁移 |
— | ●● |
SaveInterfaceInput / InterfaceOutput |
● | ●● |
InterfaceService |
● | ●● |
ParameterService |
● | ●● |
FormParameterService |
— | ●● |
DefaultForwardFlow |
● | ●●● |
InterfaceForwardQuery |
● | ●● |
InterfaceMapRepository / InterfaceMapService |
● | ●● |
ServiceProviderImportExportService |
● | ●● |
GlobalConst / ParameterPlaceholder |
● | ● |
ServiceProviderAuthService |
○ | ● |
| 测试项目 | ● | ●●● |
图例:— 无 ○ 可选 ● 必改 ●● 重度 ●●● 重构
5.2 前端 oms0414(约)
| 路径/模块 | 方案 A | 方案 B |
|---|---|---|
InterfaceDetail/index.vue |
●● | ●●● |
ServiceProviderInterfaceModal.vue |
● | ●● |
curlToInterfaceFill.ts |
● | ●● |
constants/itfxEnums.ts + docs/itfx枚举说明.md |
● | ●● |
api/InterfaceServices/typings.d.ts |
● | ●● |
| 上游映射配置页 | ● | ●● |
ApiTest/index.vue(抽组件) |
— | ●● |
downstreamInterface/newPort.vue |
○ | ●● |
6. 行为对比(典型:1688 / FormUrlEncoded)
| 步骤 | 现状 | 方案 A | 方案 B |
|---|---|---|---|
| 定义 JSON 订单结构 | 写在 Body 参数树 | 写在 Mapping Body 树 | 同 A |
表单字段 notifyBizEventDTO |
$FromBody |
$FromMappingBody |
$FromMappingBody(在 Body 表单 Tab) |
URL ?a=1 |
Fixed Query 或没有 | 仍 Fixed / 没有 | Query 表单 Tab |
Header sign |
固定配置 + 脚本 | 同左 | Header 表单 Tab |
| 上游映射配置 | 对下游 in 树 alias | 对 MappingBody alias | 同 A |
7. 选型建议
表单 JSON 映射问题
│
┌───────────────┴───────────────┐
│ │
仅 FormUrlEncoded 等少数接口 希望全站 UI/行为
需要拆映射体 与 ApiTest 完全一致
│ │
▼ ▼
【方案 A 小改】 【方案 B 大改】
优先落地、可迭代 单独立项、版本窗口
| 若你的情况是… | 建议 |
|---|---|
| 主要痛点是「form 里 JSON 字段 + 上游映射对不上」 | 方案 A |
| 同时要强改 Query/Header 配置方式、去掉固定配置双轨 | 方案 B(或 A 上线后再做 B 的第二阶段) |
| 资源紧、要先上线 | A;B 里「form 分 position」可单独立项 |
推荐路径:先做方案 A → 验证 $FromMappingBody + 映射发布 → 若仍纠结 Query/Header 体验,再开 方案 B 第二阶段(只迁 t_parameter_form.FieldPosition + RequestAsync,Mapping Body 不再动)。
8. 方案 A 实施 checklist(可直接拆任务)
- DB:
t_parameter.ParaKind+ 默认值 - 实体/DTO/枚举:
ParameterPlaceholder.FromMappingBody GetInterfaceById/SaveInterface增加mappingBodyParameterList+ 兼容InParamTreeList/ 映射 SQL 使用 MappingBodyDefaultForwardFlow占位符- 导入导出
- 前端 Mapping Body Tab + 保存字段
- curl 智能填充推断
$FromMappingBody - 文档
itfx枚举说明.md更新 - 选 1~2 个 FormUrlEncoded 生产接口回归 + 发布
9. 方案 B 实施 checklist(摘要)
- 产品定稿:Json 接口 in 树 vs MappingBody 分工;Fixed 是否保留
- DB 迁移脚本 + 回滚脚本
- Form 分 position 全链路
RequestAsync三分支组装- 接口契约 v2(可
/Interface/SaveInterfaceV2并行一期) - 前端 InterfaceDetail 重写 + 组件抽取
- 映射/授权/导出/发布全量回归
- 灰度:按服务商或接口标签切换
10. 附录:与 API 调试(ApiTest)结构对齐度
| 能力 | ApiTest | 现状 | 方案 A | 方案 B |
|---|---|---|---|---|
| Query KV | ✅ | ⚠️ 名是 Query 实为 form | ⚠️ | ✅ |
| Body KV / Raw | ✅ | ⚠️ 树在 Body | ⚠️ form 仍在 Query 表 | ✅ |
| Header KV | ✅ | ⚠️ 在固定配置 | ⚠️ | ✅ |
| 映射 JSON 结构 | — | ⚠️ 混在 in 树 | ✅ Mapping Body | ✅ |
$FromMappingBody |
— | ❌ | ✅ | ✅ |
文档版本:2026-06-02 · 基于 itfx-master + oms0414 下游接口/ApiTest 代码梳理