Feign返回text/plain导致DecodeException问题与解决方案
1. 问题现象
在 Spring Cloud 项目集成 Feign 时,调用第三方/后端接口返回如下报错:
feign.codec.DecodeException: Could not extract response: no suitable HttpMessageConverter found for response type [class ...WechatMiniCode2SessionResponse] and content type [text/plain]
原因分析
- 后端接口返回的
Content-Type
为text/plain
- Feign 客户端(Spring Cloud OpenFeign)本地需要将响应反序列化为 Java 对象,但 Spring 自动配置的
HttpMessageConverter
没有对应类型的转换器 - 导致 Feign 在反序列化时找不到合适的 Converter,抛出 DecodeException
2. 解决思路
2.1 建议优先方案:让接口返回 application/json
- 如果你能够修改服务端接口代码,建议将响应内容的
Content-Type
设置为application/json
,这样 Feign 可以自动序列化为 Java 对象
示例代码(Spring MVC Controller):
@ResponseBody
@RequestMapping(value = "/api/xxx",produces = MediaType.APPLICATION_JSON_VALUE
)
public WechatMiniCode2SessionResponse someHandler(...) {...
}
2.2 不能修改后端时的解决方案
Feign局部配置,让Jackson支持 text/plain
自定义 Feign 的 Decoder,让 MappingJackson2HttpMessageConverter 支持 text/plain
:
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.codec.Decoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.util.Arrays;
import java.util.List;@Configuration
public class FeignConfig {@Beanpublic Decoder feignDecoder() {// 添加对text/plain的支持MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));List<HttpMessageConverter<?>> converters = Arrays.asList(converter);ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(converters);return new SpringDecoder(objectFactory);}
}
然后在 FeignClient 接口上配置:
@FeignClient(name = "your-service", configuration = FeignConfig.class)
public interface YourFeignClient {@PostMapping("/api/xxx")WechatMiniCode2SessionResponse code2session(...);
}