458 lines
15 KiB
Markdown
458 lines
15 KiB
Markdown
我会对照方案读取现有接口保存、参数实体和转发组装代码,判断改造影响面与风险点。
|
||
|
||
Created 4 todos
|
||
|
||
Searched for files matching `**/src/InterfaceForward.Repositories/**/*.cs`, 80 matches
|
||
|
||
我会并行读取关键实体、DTO、保存查询服务和转发构建代码,形成可行性判断。
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Repositories/Parameter/Entities/ParameterEntity.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Repositories/Parameter/Entities/FormParameterEntity.cs)
|
||
|
||
Searched for files matching `**/src/**/FixedParameter*.cs`, 5 matches
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Repositories/Parameter/Entities/FixedParameterEntity.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application.Contracts/Dtos/Interface/SaveInterfaceInput.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application.Contracts/Dtos/Interface/ParameterInput.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application.Contracts/Dtos/Interface/SaveParameterMapsInput.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application.Contracts/Dtos/Interface/ParameterParseOutput.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application.Contracts/Dtos/ServiceProvider/FixedParameterInput.cs)
|
||
|
||
我已读取实体和 DTO,下一步查看保存/查询接口与转发上下文构建,判断方案 B 的改动点是否闭环。
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application/Services/Interface/InterfaceService.cs#1-1), lines 1 to 260
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application/Services/Interface/InterfaceService.cs#260-260), lines 260 to 334
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application/Services/Parameter/ParameterService.cs#1-1), lines 1 to 260
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application/Services/Parameter/ParameterService.cs#260-260), lines 260 to 560
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application/Services/Parameter/FormParameterService.cs)
|
||
|
||
我继续读取上下文构建和映射查询代码,确认方案里 `InParamTreeList` 来源切换的实现难度。
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application/Services/InterfaceForwardCommon.cs#1-1), lines 1 to 260
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Application/Services/InterfaceForwardCommon.cs#260-260), lines 260 to 420
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Repositories/InterfaceForwardQuery.cs)
|
||
|
||
关键转发查询显示目前仍把下游所有 `IsInPara=true` 当映射树,且 Form KV 未区分 Query/Header/Body;我再查看 DTO/枚举常量后给出结论。
|
||
|
||
Searched for regex `enum FieldPosition|enum ContentType|FromBody|FromMappingBody|FormFieldList|FixedFieldList` (`**/src/**`), 79 results
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Domain.Shared/Enum/FieldPosition.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Domain.Shared/Enum/ContentType.cs)
|
||
|
||
已有 `FieldPosition` 和 `ContentType` 枚举基本符合方案,但 `t_parameter_form` 实体缺 `FieldPosition`,`t_parameter` 缺 `ParaKind`,这是数据库层主要增量。
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Domain.Shared/GlobalConst.cs)
|
||
|
||
Read [](file:///d%3A/my/itfx/itfx/src/InterfaceForward.Domain.Shared/Dtos/ForwardCoreContextCache.cs)
|
||
|
||
Completed: *梳理现有数据模型* (1/4)
|
||
|
||
可行,但这是**中大型重构**,不是小改。方案 B 和当前代码方向一致,主要是把现在“下游入参树 + 表单参数 + 固定参数”混用的问题拆清楚。建议可以做,但要按阶段推进。
|
||
|
||
## 总体结论
|
||
|
||
**可行性:高。**
|
||
**改造成本:中高。**
|
||
**主要风险:映射保存/发布缓存/转发组装三处需要同步改,否则容易出现保存成功但转发错误。**
|
||
|
||
方案 B 的核心改动和现有代码冲突点主要有 3 个:
|
||
|
||
1. 当前下游统一使用 `InParameterList` 作为映射树。
|
||
2. 当前 `t_parameter_form` 没有 `FieldPosition`,无法区分 Query / Header / Body。
|
||
3. 当前转发时 FormUrlEncoded 用 `$FromBody`,方案要求改成 `$FromMappingBody`。
|
||
|
||
---
|
||
|
||
## 当前代码现状
|
||
|
||
### 1. `t_parameter` 当前只有 `IsInPara`
|
||
|
||
实体在 ParameterEntity.cs:
|
||
|
||
```csharp
|
||
public bool IsInPara { get; set; }
|
||
```
|
||
|
||
目前语义是:
|
||
|
||
- `IsInPara = true`:入参
|
||
- `IsInPara = false`:出参
|
||
|
||
但方案 B 需要进一步区分:
|
||
|
||
- 上游入参
|
||
- 下游 Json/Xml RequestBody
|
||
- 下游 FormUrlEncoded MappingBody
|
||
- 出参
|
||
|
||
所以需要新增:
|
||
|
||
```csharp
|
||
public ParameterParaKind ParaKind { get; set; }
|
||
```
|
||
|
||
或类似枚举:
|
||
|
||
```csharp
|
||
public enum ParameterParaKind
|
||
{
|
||
Normal = 0,
|
||
MappingBody = 1
|
||
}
|
||
```
|
||
|
||
### 2. `t_parameter_form` 当前没有 `FieldPosition`
|
||
|
||
实体在 FormParameterEntity.cs,当前只有:
|
||
|
||
```csharp
|
||
public string Name { get; set; }
|
||
public string Value { get; set; }
|
||
public string Description { get; set; }
|
||
```
|
||
|
||
方案 B 要它承载:
|
||
|
||
- Query KV
|
||
- Header KV
|
||
- Body KV
|
||
|
||
所以必须新增:
|
||
|
||
```csharp
|
||
public FieldPosition FieldPosition { get; set; }
|
||
```
|
||
|
||
现有 `FieldPosition` 枚举已经存在于 FieldPosition.cs,可直接复用。
|
||
|
||
### 3. `SaveInterfaceInput` 当前字段不够
|
||
|
||
当前 SaveInterfaceInput.cs 只有:
|
||
|
||
```csharp
|
||
public List<ParameterInput> InParameterList { get; set; }
|
||
public List<ParameterInput> OutParameterList { get; set; }
|
||
public List<FormParameterInput> FormParameterList { get; set; }
|
||
```
|
||
|
||
方案 B 要改成:
|
||
|
||
```csharp
|
||
public List<FormParameterInput> QueryFormParameterList { get; set; }
|
||
public List<FormParameterInput> HeaderFormParameterList { get; set; }
|
||
public List<FormParameterInput> BodyFormParameterList { get; set; }
|
||
|
||
public List<ParameterInput> InParameterList { get; set; }
|
||
public List<ParameterInput> RequestBodyParameterList { get; set; }
|
||
public List<ParameterInput> MappingBodyParameterList { get; set; }
|
||
public List<ParameterInput> OutParameterList { get; set; }
|
||
```
|
||
|
||
不做旧字段兼容的话,这个改动是合理的。
|
||
|
||
---
|
||
|
||
## 转发逻辑可行性
|
||
|
||
### 当前链路
|
||
|
||
当前构建转发上下文在 InterfaceForwardQuery.cs:
|
||
|
||
```csharp
|
||
var inParaMaps = await GetParameterMapListAsync(mapIds, true);
|
||
...
|
||
InParamTreeList = JsonHelper.BuildTreeList(items)
|
||
FormFieldList = await GetFormFieldListAsync(targetInterface.Id)
|
||
FixedFieldList = fixedFieldList
|
||
```
|
||
|
||
当前问题是:
|
||
|
||
- 下游所有 `IsInPara=true` 都被当成映射目标。
|
||
- FormUrlEncoded 和 Json 的映射树没有语义区分。
|
||
- Query/Header 主要还依赖 `FixedFieldList` 或旧 `FormFieldList`。
|
||
|
||
方案 B 的调整是可落地的:
|
||
|
||
| ContentType | `InParamTreeList` 来源 |
|
||
| -------------- | -------------------------- |
|
||
| Json / Xml | `requestBodyParameterList` |
|
||
| FormUrlEncoded | `mappingBodyParameterList` |
|
||
| 上游 | `inParameterList` |
|
||
|
||
这需要改 `GetParameterMapListAsync()` 查询条件:
|
||
|
||
- Json/Xml:查 `t_parameter.IsInPara = true AND ParaKind = Normal`
|
||
- FormUrlEncoded:查 `t_parameter.IsInPara = true AND ParaKind = MappingBody`
|
||
- 出参:仍查 `IsInPara = false`
|
||
|
||
---
|
||
|
||
## HTTP 组装改造可行性
|
||
|
||
当前 DefaultForwardFlow.cs 已经有这些能力:
|
||
|
||
- Query 拼接
|
||
- Header 拼接
|
||
- FormUrlEncoded Body 组装
|
||
- Json/XML Body 序列化
|
||
- 占位符替换
|
||
|
||
所以不是推倒重来,而是调整来源。
|
||
|
||
### 当前 FormUrlEncoded
|
||
|
||
当前逻辑大致是:
|
||
|
||
```csharp
|
||
if (context.FormFieldList.Count != 0)
|
||
{
|
||
var field = context.FormFieldList.FirstOrDefault(x => x.Value == GlobalConst.FromBody);
|
||
if (field != null) field.Value = body;
|
||
nameValueCollection = context.FormFieldList.ToDictionary(x => x.Name, x => x.Value);
|
||
}
|
||
```
|
||
|
||
方案 B 要改为:
|
||
|
||
```csharp
|
||
$FromMappingBody
|
||
```
|
||
|
||
并且 `FormFieldList` 只取 `FieldPosition = Body`。
|
||
|
||
Query/Header 不应该混在 `FixedFieldList` 的接口级配置里,而应来自:
|
||
|
||
```csharp
|
||
queryFormParameterList
|
||
headerFormParameterList
|
||
```
|
||
|
||
---
|
||
|
||
## 数据库改造建议
|
||
|
||
需要新增字段:
|
||
|
||
### `t_parameter_form`
|
||
|
||
```sql
|
||
ALTER TABLE t_parameter_form
|
||
ADD FieldPosition INT NOT NULL DEFAULT 2;
|
||
```
|
||
|
||
默认 `2 = Body`,这样老数据如果不迁移也能先当 Body。
|
||
|
||
### `t_parameter`
|
||
|
||
```sql
|
||
ALTER TABLE t_parameter
|
||
ADD ParaKind INT NOT NULL DEFAULT 0;
|
||
```
|
||
|
||
默认 `0 = Normal`。
|
||
|
||
如果真的“不做旧字段兼容,全量重构”,可以不迁移旧语义;但数据库字段还是要加。
|
||
|
||
---
|
||
|
||
## 主要影响面
|
||
|
||
### 必改
|
||
|
||
| 模块 | 文件/区域 | 影响 |
|
||
| ---------------- | ----------------------- | ---------------------------------------------- |
|
||
| DTO | `SaveInterfaceInput` | 入参结构重构 |
|
||
| DTO | `FormParameterInput` | 新增 `FieldPosition` |
|
||
| DTO | `ParameterInput` | 新增 `ParaKind` |
|
||
| Entity | `FormParameterEntity` | 新增 `FieldPosition` |
|
||
| Entity | `ParameterEntity` | 新增 `ParaKind` |
|
||
| SaveInterface | `InterfaceService` | 按 ContentType 互斥保存 |
|
||
| GetInterfaceById | `InterfaceService` | 按 ContentType 拆分返回 |
|
||
| 参数服务 | `ParameterService` | 保存/查询支持 `ParaKind` |
|
||
| 表单服务 | `FormParameterService` | 保存/查询支持 `FieldPosition` |
|
||
| 转发查询 | `InterfaceForwardQuery` | 映射树按 ContentType 选择 |
|
||
| 转发执行 | `DefaultForwardFlow` | `$FromMappingBody`、Query/Header/Form 来源调整 |
|
||
|
||
### 可能要改
|
||
|
||
| 模块 | 原因 |
|
||
| ---------------------------- | --------------------------------------------------------- |
|
||
| `InterfaceMapService` | 映射页面可能依赖下游 `InParameterList` |
|
||
| `InterfaceMapPublishService` | 发布缓存构建依赖参数树 |
|
||
| `FixedParameterService` | 方案要求删除接口级 Fixed 维护 |
|
||
| 导入导出 | 如果导出接口配置,需要更新结构 |
|
||
| 脚本助手 | 需要支持 `$FromMappingBody` 和新的 Query/Header/Body 结构 |
|
||
|
||
---
|
||
|
||
## 最大风险点
|
||
|
||
### 1. 映射页面风险最高
|
||
|
||
当前映射保存结构在 SaveParameterMapsInput.cs。
|
||
|
||
它的 `ParaId` 指向下游参数。
|
||
|
||
方案 B 后:
|
||
|
||
- Json/Xml 下游:`ParaId` 指向 `requestBodyParameterList`
|
||
- FormUrlEncoded 下游:`ParaId` 指向 `mappingBodyParameterList`
|
||
- Header/Query/BodyForm KV 不参与普通参数映射,除非值为 `$FromMappingBody`
|
||
|
||
这个规则必须前后端统一,否则映射会乱。
|
||
|
||
### 2. 缓存风险
|
||
|
||
转发上下文会缓存:
|
||
|
||
```csharp
|
||
ForwardContext:up_{upStreamCode}:sp_{serviceProviderCode}
|
||
```
|
||
|
||
重构后发布接口/保存接口必须清理或重建缓存,否则会拿旧结构转发。
|
||
|
||
### 3. FormUrlEncoded 行为变化
|
||
|
||
旧逻辑用 `$FromBody`,新逻辑用 `$FromMappingBody`。
|
||
|
||
如果现有表单配置里已经有 `$FromBody`,全量重构可以不兼容,但测试环境必须重新配置。
|
||
|
||
### 4. 接口级 Fixed 删除要谨慎
|
||
|
||
`t_parameter_fixed` 当前支持:
|
||
|
||
```csharp
|
||
ServiceProviderId
|
||
InterfaceId
|
||
```
|
||
|
||
方案要求删除接口级 Fixed 维护,但代码里 InterfaceForwardQuery.cs 仍会查:
|
||
|
||
```csharp
|
||
a.ServiceProviderId == serviceProviderId || a.InterfaceId == interfaceId
|
||
```
|
||
|
||
如果彻底删除接口级 Fixed,需要改成只查服务商级:
|
||
|
||
```csharp
|
||
a.ServiceProviderId == serviceProviderId
|
||
```
|
||
|
||
否则旧数据仍会生效。
|
||
|
||
---
|
||
|
||
## 推荐实施顺序
|
||
|
||
### 第一阶段:数据模型和 DTO
|
||
|
||
1. 新增 `ParameterParaKind` 枚举。
|
||
2. `ParameterEntity` 新增 `ParaKind`。
|
||
3. `ParameterInput` 新增 `ParaKind`。
|
||
4. `FormParameterEntity` 新增 `FieldPosition`。
|
||
5. `FormParameterInput` / `FormParameterItem` 新增 `FieldPosition`。
|
||
6. `SaveInterfaceInput` 拆分字段。
|
||
|
||
### 第二阶段:保存/查询接口
|
||
|
||
改 InterfaceService.cs:
|
||
|
||
- 上游:只保存 `inParameterList`
|
||
- 下游 Json/Xml:只保存 `requestBodyParameterList`
|
||
- 下游 FormUrlEncoded:保存 `bodyFormParameterList` + `mappingBodyParameterList`
|
||
- 所有类型:保存 `queryFormParameterList` + `headerFormParameterList`
|
||
- 所有类型:保存 `outParameterList`
|
||
|
||
并加入互斥校验。
|
||
|
||
### 第三阶段:转发查询
|
||
|
||
改 InterfaceForwardQuery.cs:
|
||
|
||
- `GetParameterMapListAsync()` 支持 `ParaKind`
|
||
- `GetFormFieldListAsync()` 改成按 `FieldPosition` 获取
|
||
- 构建 `TargetInterfaceSummary` 时区分:
|
||
- `QueryFieldList`
|
||
- `HeaderFieldList`
|
||
- `BodyFormFieldList`
|
||
- `InParamTreeList`
|
||
|
||
### 第四阶段:转发执行
|
||
|
||
改 DefaultForwardFlow.cs:
|
||
|
||
- `ReplacePlaceholder()` 支持 `$FromMappingBody`
|
||
- Query 从 Query KV 来
|
||
- Header 从 Header KV 来
|
||
- FormUrlEncoded Body 从 Body KV 来
|
||
- Json/Xml Body 保持序列化 `OriginalInterfaceMappedInput`
|
||
|
||
### 第五阶段:映射与发布
|
||
|
||
重点改:
|
||
|
||
- 映射详情查询
|
||
- 映射保存
|
||
- 发布缓存
|
||
- 缓存清理
|
||
|
||
### 第六阶段:测试
|
||
|
||
建议新增测试覆盖:
|
||
|
||
1. 下游 Json:`requestBodyParameterList` 映射并序列化为 JSON。
|
||
2. 下游 Xml:`requestBodyParameterList` 映射并序列化为 XML。
|
||
3. FormUrlEncoded:`mappingBodyParameterList` 映射,`bodyFormParameterList` 中 `$FromMappingBody` 被替换。
|
||
4. Query:所有 ContentType 都能拼 Query。
|
||
5. Header:所有 ContentType 都能加 Header。
|
||
6. 上游:仍只使用 `inParameterList`。
|
||
7. 接口级 Fixed 不再生效。
|
||
8. 服务商级 Fixed 仍生效。
|
||
|
||
---
|
||
|
||
## 可行性评级
|
||
|
||
| 项 | 评级 |
|
||
| ---------------------- | ---------------------------- |
|
||
| 技术可行性 | 高 |
|
||
| 代码改动量 | 中高 |
|
||
| 数据库改动风险 | 中 |
|
||
| 前端联动成本 | 高 |
|
||
| 转发链路风险 | 中高 |
|
||
| 是否建议做 | 建议做 |
|
||
| 是否适合一次性全量重构 | 可以,但必须有测试和联调环境 |
|
||
|
||
---
|
||
|
||
## 最终建议
|
||
|
||
方案 B 是正确方向,尤其解决了当前这几个长期隐患:
|
||
|
||
- Form 参数和 Query/Header 混用。
|
||
- 下游 `InParameterList` 语义不清。
|
||
- Json Body 和 Form Mapping Body 混用。
|
||
- `$FromBody` 表达不准确。
|
||
- 接口级 Fixed 和接口参数配置职责重叠。
|
||
|
||
建议按**全量重构**执行,但不要边改边猜。最好先做后端闭环:
|
||
|
||
```text
|
||
DB 字段 → DTO → Save/Get → ForwardContext → ForwardFlow → Tests
|
||
```
|
||
|
||
等后端测试跑通后,再让前端按方案 B 调整页面。 |