DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS

Feign 表单传 int[] 报 ClassCastException,数组不能直接当 Object[]

Feign 13.16 的表单编码器把数组直接转成 Object[],int[] 等基本类型数组会在请求发出前失败。正式 13.17 已按元素访问数组;旧环境可只在需要多值的字段边界逐项装箱,保留 multipart byte[] 的二进制含义。

Feign 的表单字段传入 int[] {1, 2},没有收到 HTTP 响应,调用就先报 ClassCastException;换成普通引用类型集合又能编码。此时应检查 FormEncoder 的数组处理,而不是继续调整服务端表单解析。

正式 Feign 13.16 的 URL 表单路径先判断 isArray(),然后把值转成 Object[]。Java 的 int[]、long[] 等基本类型数组并不是 Object[],所以“已经确认是数组”仍不足以保证这次强转合法。multipart 的多值 writer 选择也有同类强转路径。

13.17 改为按元素读取数组

正式 13.17 已引入统一的数组元素访问,基本类型数组经过反射读取并装箱,不再依赖把整个数组强转成引用数组。URL 编码继续使用原来的 CollectionFormat,多值如何拼接仍取决于所配置的表单格式。

按工程既有 BOM 或依赖管理采用兼容的 13.17 或包含同项修正的正式版本,核对实际使用的 feign-form 与 core。使用 Spring Cloud OpenFeign 等框架管理时,还要确认框架的依赖组合与 Encoder 实际选择;只更新一个没有被调用的编码器不能证明入口改变。

编码异常发生在本地,不应通过改服务端字段名或重试网络请求掩盖。先确认堆栈指向 UrlencodedFormContentProcessor 或 ManyParametersWriter,输入确为基本类型数组;其他 EncodeException 仍有自己的条件。

旧环境可以在明确的多值字段上装箱

暂时不能更新时,对于本来表示重复整数值的字段,可将非 null 的 int[] 显式转换为 List<Integer> 后交给原表单编码器:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

List<Integer> formIds = Arrays.stream(ids)
    .boxed()
    .collect(Collectors.toList());

这里的 ids 是应用已有的非 null int[],片段需要 Java 8 或更新版本。将 formIds 放到原来的表单字段位置,保留字段名和 CollectionFormat;不要把它改成一段未经约定的 JSON 字符串。

Arrays.asList(ids) 不会逐个装箱,它得到的是只包含这个 int[] 的列表。外面再包 ArrayList 也没有展开元素。若原协议区分 null 与空数组,还应在转换之前按原约定处理,不能把两者随手合并。

multipart 的 byte[] 不能一起拆开

byte[] 在 multipart 中可能表示一个文件或二进制 part。13.17 保留专门的 ByteArrayWriter,将完整字节写入一个 part;不能为了统一转换,给所有数组都套上逐项 List 化。

对需要重复标量值的字段与二进制上传字段分别验收。URL 表单检查字段名、编码后的值、空输入与原来的连接规则;multipart 则还要检查 part 数量、边界、内容类型和二进制内容逐字节一致。升级不能被理解为新增了所有字符类型或自定义对象的 multipart 支持,仍需遵守对应 writer 的适用范围。

最后确认异常前后的请求发送行为。旧路径通常在编码阶段失败;改动后请求会真正发出,应使用受控目标检查结果,涉及写入接口时沿用原有幂等规则,不把之前的失败次数直接变成补发次数。