
当Feign客户端调用返回纯文本(如字符串"OK")而非标准JSON的接口时,因默认JSON解码器无法解析非结构化响应,会抛出Unrecognized token 'OK'异常;需自定义Decoder绕过JSON解析,直接处理原始响应体。
当Feign客户端调用返回纯文本(如字符串"OK")而非标准JSON的接口时,因默认JSON解码器无法解析非结构化响应,会抛出Unrecognized token 'OK'异常;需自定义Decoder绕过JSON解析,直接处理原始响应体。
在Spring Cloud Feign中,客户端默认使用JacksonDecoder(或SpringDecoder)对HTTP响应体进行反序列化。但当目标服务仅返回明文字符串(如HTTP 200响应体为纯OK),而Feign接口方法声明返回类型为String且未显式指定produces = MediaType.TEXT_PLAIN_VALUE,Feign仍会尝试以JSON方式解析该响应——导致解析失败并抛出FeignException: Unrecognized token 'OK'。
根本原因在于:Feign的默认解码逻辑与服务实际响应格式不匹配。即使你在@PostMapping中已添加produces = MediaType.TEXT_PLAIN_VALUE,若未配合启用文本友好型解码器,Feign仍可能忽略该声明并强制走JSON路径。
✅ 推荐解决方案:注册自定义Decoder,专用于处理text/plain响应
@Configuration
public class FeignConfig {
@Bean
public Decoder feignDecoder() {
return new StringDecoder();
}
// 自定义解码器:对 text/plain 响应直接读取字符串,跳过JSON解析
static class StringDecoder implements Decoder {
private final Decoder defaultDecoder = new SpringDecoder(() -> new GenericJackson2JsonDecoder());
@Override
public Object decode(Response response, Type type) throws IOException {
// 检查响应Content-Type是否为text/plain且目标类型为String
String contentType = response.headers().get("Content-Type")
.stream()
.filter(s -> s != null)
.findFirst()
.orElse("");
if (type == String.class && contentType.toLowerCase().contains("text/plain")) {
return Util.toString(response.body().asReader(StandardCharsets.UTF_8));
}
// 其他情况(如JSON、对象等)交由默认解码器处理
return defaultDecoder.decode(response, type);
}
}
}
? 关键注意事项:
- 该
Decoder必须通过@Bean注入,并确保其作用于对应@FeignClient(可通过configuration = FeignConfig.class显式指定); -
@FeignClient接口中必须保留produces = MediaType.TEXT_PLAIN_VALUE,否则Feign可能无法正确识别响应类型; - 若服务偶发返回JSON错误体(如
{"error":"..."}),建议增强StringDecoder逻辑:根据response.status()判断是否需要降级解析,或结合ErrorDecoder统一处理异常响应; - 避免全局替换为纯字符串解码器——仅对明确返回纯文本的客户端生效,以保障其他JSON接口的兼容性。
通过此方案,Feign将智能区分响应类型:对text/plain直接转String,对application/json仍走标准Jackson反序列化,兼顾灵活性与健壮性。










