15 KiB
方案 B 重构清单(前后对比 · 修订版)
前提:全量重构,不做旧字段兼容。
修订要点:先定义「一次 HTTP 请求」应保存哪些结构,再说明 Mapping Body 仅在某些 Content-Type 下才存在;application/json的请求体参数树 本身就是映射体,不单独拆 Mapping Body。
1. 设计顺序(先看这个)
第一步 请求接口应保存什么(与 Content-Type 无关 + 有关部分分开)
Query / Header / Body 传输层 + 响应 + 基本信息
第二步 映射体放哪(由 Content-Type 决定)
Json/Xml → Body 参数树 = 映射体
Form 类 → 传输用表单 KV + 独立 Mapping Body 树(表单字段可 $FromMappingBody)
Mapping Body 不是每个接口都有,只有「Body(或 Query)走表单 KV,且业务 JSON 需要单独做上游映射」时才配置。
2. 改造后:一次请求应保存什么(目标模型)
2.1 与 Content-Type 无关(任何下游接口都有)
| 存储 | 表 | UI(对齐 ApiTest) | 说明 |
|---|---|---|---|
| 基本信息 | t_interface |
地址、Method、Protocol、ContentType、QPS… | 不变 |
| Query | t_parameter_form(FieldPosition=Query) |
Query Tab,KV | 真实 URL Query,不仅 FormUrlEncoded 才有 |
| Header | t_parameter_form(FieldPosition=Header) |
Header Tab,KV | 请求头;占位符 $TimeStamp、$token 等 |
| Response | t_parameter(IsInPara=false) |
Response 参数树 | 不变 |
| 返回配置 | t_interface_return_config |
返回配置 Tab | 不变 |
| cURL 示例 | t_interface.InParams |
cURL Tab | 不变 |
| 服务商级 Fixed | t_parameter_fixed(ServiceProviderId) |
不在接口明细维护 | Url 占位、服务商通用 Header、脚本写入 |
2.2 与 Content-Type 有关(Body 区不同)
| ContentType | Body 传输层保存什么 | 映射体保存什么 | 是否需要 Mapping Body |
|---|---|---|---|
| Json (3) | requestBodyParameterList 参数树 |
同一棵树 | 否 |
| Xml (4) | requestBodyParameterList 参数树 |
同一棵树 | 否 |
| FormUrlEncoded (1) | bodyFormParameterList KV |
mappingBodyParameterList 参数树 |
是 |
| FormData (2) | 二期:bodyForm 或 multipart 描述 |
若字段内嵌 JSON,同 FormUrlEncoded | 二期 |
| 上游接口 | inParameterList 树(业务入参) |
同一棵树 | 否 |
2.3 结构总图(改造后)
┌─ 基本信息 (t_interface)
│
任意 Content-Type ├─ queryFormParameterList (t_parameter_form, Query)
├─ headerFormParameterList (t_parameter_form, Header)
│
├─ Body 区 ─────────────────────────────────────┐
│ │
│ Json/Xml FormUrlEncoded │
│ requestBody bodyFormParameterList │
│ ParameterList (KV 传输) │
│ (树=映射体) mappingBodyParameterList │
│ (树=仅映射体) │
└────────────────────────────────────────────────┘
│
├─ outParameterList (出参树)
└─ inParams (cURL 示例)
2.4 页面 Tab(下游接口 · 按 Content-Type 显示)
| Tab | Json / Xml | FormUrlEncoded |
|---|---|---|
| Query | 显示 KV | 显示 KV |
| Header | 显示 KV | 显示 KV |
| Body | 参数树(= 映射体) | KV 表(传输) |
| Mapping Body | 隐藏 | 显示(参数树) |
| cURL | 显示 | 显示 |
| Response | 显示 | 显示 |
| 删除(接口级) | 删除 |
与 ApiTest 对齐方式:
- ApiTest 的 Request Tab:Json 时常用 Raw;接口配置里 Json 仍用 参数树 定义结构(itfx 现有能力,且即映射体)。
- ApiTest 的 FormUrlEncoded:URL Encoded KV = 我们的 bodyForm;映射结构不在调试页里,在接口配置里用 Mapping Body 维护。
3. Mapping Body 何时存在(规则定稿)
| 条件 | 结论 |
|---|---|
ContentType = Json 或 Xml |
没有 mappingBodyParameterList;requestBodyParameterList 参与 InParamRestructure 且被 SerializationBody 序列化 |
ContentType = FormUrlEncoded |
有 bodyFormParameterList + 有 mappingBodyParameterList;映射只对 Mapping Body 树;表单字段值可为 $FromMappingBody |
| Query 上也有「值为 JSON」的罕见情况 | 仍用 Mapping Body 树做映射,Query KV 里字段填 $FromMappingBody(与 Body 表单同理) |
上游 IsUpStream=true |
始终只有 inParameterList,无 Mapping Body、无 bodyForm |
占位符
| 占位符 | 用于 | Content-Type |
|---|---|---|
$FromMappingBody |
Form 的 Query/Body(及必要时 Header)字段引用映射结果 | 仅 Form 类 |
$FromBody |
删除下游表单中的用法 | — |
| Json Body 树字段 | 直接映射到 alias,不需要占位符塞整段 JSON | Json / Xml |
4. 数据库(修订)
4.1 t_parameter_form — 传输层 KV
新增 FieldPosition:Header=1, Body=2, Query=3。
| FieldPosition | 何时有数据 |
|---|---|
| Query | 任意 Content-Type,有 URL 参数就配 |
| Header | 任意 Content-Type |
| Body | 主要 FormUrlEncoded;Json/Xml 通常 无 body 行(Body 在参数树) |
4.2 t_parameter — 参数树
新增 ParaKind:
| ParaKind | 含义 | 用于 |
|---|---|---|
| 0 Normal | 默认 | 出参;上游入参;Json/Xml 的 RequestBody |
| 1 MappingBody | 仅映射、不直接当 HTTP Json Body | 仅 FormUrlEncoded(及日后 FormData)且需要独立映射体时 |
| 列表字段 | ParaKind | IsInPara |
|---|---|---|
requestBodyParameterList |
Normal(或枚举值 RequestBody=0) | true |
mappingBodyParameterList |
MappingBody | true |
outParameterList |
Normal | false |
删除的用法
- 不再用「一棵 in 树」同时表示 Form 映射 + Json Body(改造前混用)。
4.3 t_parameter_fixed
- 删:接口明细维护接口级 Header/Query/Body KV。
- 留:服务商级、Url、脚本动态 Header。
5. SaveInterface / GetInterfaceById(请求结构)
POST /api/Interface/SaveInterface · 响应为接口 id(number)。
GetInterfaceById 字段与保存一致。已删除:formParameterList、下游 inParameterList。
5.1 根对象
| 字段 | 说明 |
|---|---|
optionType |
1 增 / 3 改 / 2 删 |
isUpStream |
true 上游 / false 下游 |
serviceProviderId |
上游 0 |
id |
改、删必填 |
name, requestAddress, requestProtocol, requestMethod, contentType |
基本信息 |
code, category, description, isBatch, limit, responseContentType, flowCode, isDisableAuth, qps, mappedParamType, inParams |
可选 |
queryFormParameterList |
Query KV,fieldPosition=3 |
headerFormParameterList |
Header KV,fieldPosition=1 |
outParameterList |
出参树 |
requestBodyParameterList |
仅下游 Json/Xml,Body 树 = 映射体 |
bodyFormParameterList |
仅下游 FormUrlEncoded,Body KV |
mappingBodyParameterList |
仅下游 FormUrlEncoded,映射树 |
inParameterList |
仅上游入参树 |
5.2 Body 字段互斥
| 场景 | 传 | 不传 |
|---|---|---|
下游 Json/Xml (contentType 3/4) |
requestBodyParameterList |
bodyForm*、mappingBody*、inParameterList |
下游 FormUrlEncoded (1) |
bodyFormParameterList + mappingBodyParameterList |
requestBody*、inParameterList |
| 上游 | inParameterList |
requestBody*、bodyForm*、mappingBody* |
5.3 子结构
FormParameterInput(Query / Header / Body 行)
{ "optionType": 1, "id": 0, "name": "字段名", "value": "$FromMappingBody", "description": "", "fieldPosition": 2 }
fieldPosition:1 Header · 2 Body · 3 Query。Form 业务 JSON 字段用 $FromMappingBody。
ParameterInput(树节点:requestBody / mappingBody / in / out)
{ "optionType": 1, "id": 1, "pId": 0, "name": "order", "alias": "order", "type": 3, "isRequired": true, "sort": "1", "paraKind": 0 }
paraKind:0 Normal(requestBody、上游 in、出参)· 1 MappingBody(仅 mappingBody 列表)。新增时 id/pId 需表达父子关系。
5.4 示例
下游 · Json(contentType: 3)
{
"optionType": 1,
"isUpStream": false,
"serviceProviderId": 5,
"name": "创建订单",
"requestAddress": "https://api.example.com/order",
"requestProtocol": 2,
"requestMethod": 2,
"contentType": 3,
"queryFormParameterList": [
{ "optionType": 1, "id": 0, "name": "access_token", "value": "$FromAccount", "fieldPosition": 3 }
],
"headerFormParameterList": [],
"requestBodyParameterList": [
{ "optionType": 1, "id": 1, "pId": 0, "name": "orderId", "alias": "orderId", "type": 1, "paraKind": 0 }
],
"outParameterList": []
}
下游 · FormUrlEncoded(contentType: 1)
{
"optionType": 3,
"isUpStream": false,
"serviceProviderId": 5,
"id": 1001,
"name": "1688回调",
"requestAddress": "https://gw.open.1688.com/openapi/http",
"requestProtocol": 2,
"requestMethod": 2,
"contentType": 1,
"queryFormParameterList": [
{ "optionType": 3, "id": 11, "name": "_aop_timestamp", "value": "$TimeStamp", "description": "ms", "fieldPosition": 3 }
],
"headerFormParameterList": [],
"bodyFormParameterList": [
{ "optionType": 3, "id": 10, "name": "notifyBizEventDTO", "value": "$FromMappingBody", "fieldPosition": 2 },
{ "optionType": 3, "id": 13, "name": "_aop_signature", "value": "", "fieldPosition": 2 }
],
"mappingBodyParameterList": [
{ "optionType": 3, "id": 1, "pId": 0, "name": "order", "alias": "order", "type": 3, "paraKind": 1 },
{ "optionType": 3, "id": 2, "pId": 1, "name": "orderId", "alias": "orderId", "type": 1, "paraKind": 1 }
],
"outParameterList": []
}
上游(isUpStream: true)
{
"optionType": 1,
"isUpStream": true,
"serviceProviderId": 0,
"name": "标准创建订单",
"requestAddress": "/api/order/create",
"requestProtocol": 2,
"requestMethod": 2,
"contentType": 3,
"queryFormParameterList": [],
"headerFormParameterList": [],
"inParameterList": [
{ "optionType": 1, "id": 1, "pId": 0, "name": "order", "alias": "order", "type": 3, "paraKind": 0 }
],
"outParameterList": []
}
6. 转发逻辑(修订)
6.1 映射树来源(InParamTreeList)
| ContentType | InParamTreeList 来源 |
|---|---|
| Json / Xml | requestBodyParameterList(整棵树) |
| FormUrlEncoded | mappingBodyParameterList |
| 上游 | 系统接口 inParameterList(映射配置页不变) |
6.2 HTTP 组装
| 部分 | 来源 |
|---|---|
| URL Query | queryFormParameterList(+ 服务商 Fixed Query) |
| Header | headerFormParameterList(+ 服务商 Fixed Header) |
| Body Json | Serialize(requestBodyParameterList 映射结果 ) |
| Body FormUrlEncoded | 仅 bodyFormParameterList;其中 $FromMappingBody ← 映射结果序列化 |
| Body Xml | 同 Json,Xml 序列化 |
6.3 流程对比(两张)
Json 下游(无 Mapping Body)
上游 JSON → Restructure(requestBodyParameterList) → OriginalInterfaceMappedInput
→ ReplacePlaceholder(Query/Header form + Fixed)
→ SerializationBody(Json) → HTTP Body
→ 拼 Query / Header
FormUrlEncoded 下游(有 Mapping Body)
上游 JSON → Restructure(mappingBodyParameterList) → OriginalInterfaceMappedInput
→ ReplacePlaceholder(含 bodyForm 的 $FromMappingBody)
→ bodyForm 字典 → HTTP Body
→ 拼 Query / Header
7. 前后对比总表(增删改)
7.1 删除了什么
| 类别 | 内容 |
|---|---|
| API | 下游 formParameterList、下游笼统的 inParameterList(拆开后互斥) |
| UI | 固定配置 Tab;接口级 Fixed API |
| 语义 | 所有下游共用一棵 in 树;Form 无 position;Json 也搞 Mapping Body Tab |
| 占位 | 下游表单用 $FromBody 表示整段 JSON |
7.2 新增了什么
| 类别 | 内容 |
|---|---|
| 表 | t_parameter_form.FieldPosition;t_parameter.ParaKind |
| API | queryFormParameterList、headerFormParameterList(全类型共有) |
| API | bodyFormParameterList(仅 Form 类) |
| API | requestBodyParameterList(仅 Json/Xml,=映射体) |
| API | mappingBodyParameterList(仅 Form 类) |
| UI | Header Tab;Form 时 Mapping Body Tab;Json 时 Body=树 |
| 占位 | $FromMappingBody(仅 Form KV) |
7.3 改了什么
| 项 | 改造前 | 改造后 |
|---|---|---|
| Query | 假 Query(实为 form body) | 真 Query KV,所有 Content-Type |
| Body Tab | 永远是参数树 | Json=树;Form=KV |
| 映射体 | 永远 in 树 | Json=Body 树;Form=Mapping Body 树 |
| 保存 | form + in 混传 | 按 ContentType 传 互斥 的 Body 相关列表 |
| 映射 SQL | 下游 IsInPara 全量 | Json:RequestBody 树;Form:ParaKind=MappingBody |
8. Content-Type 全量对照(改造后)
| ContentType | queryForm | headerForm | bodyForm | requestBody 树 | mappingBody 树 | 映射目标 | HTTP Body |
|---|---|---|---|---|---|---|---|
| Json | 可选 | 可选 | 不用 | 必填 | 不用 | requestBody 树 | 序列化该树 |
| Xml | 可选 | 可选 | 不用 | 必填 | 不用 | requestBody 树 | Xml 序列化 |
| FormUrlEncoded | 常用 | 常用 | 必填 | 不用 | 必填 | mappingBody 树 | bodyForm 字典 |
| FormData | 二期 | 二期 | 二期 | 不用 | 二期 | 二期 | 二期 |
| 上游 Json | — | — | — | inParameterList | — | in 树 | — |
9. 一句话
| 改造前 | 改造后 | |
|---|---|---|
| 先保存什么 | form + in 混在一起 | 先 Query/Header(通用)+ 再按 Content-Type 存 Body |
| Json | in 树 = 映射 + Body | requestBody 树 = 映射体,不要 Mapping Body |
| Form | in 树 + form 表 | bodyForm 传输 + mappingBody 映射 |
| Mapping Body | (之前文档)每个下游都有 | 仅 Form 类需要 |
文档版本:2026-06-02 · 含 SaveInterface 结构与示例(§5)