You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FeignClient抛异常而非返回错误状态ResponseEntity的解决方法

解决FeignClient返回ResponseEntity时抛出FeignException的问题

我明白你遇到的困扰:明明声明FeignClient方法返回ResponseEntity<T>,但服务端返回400这类非2xx状态码时,程序直接抛出FeignException,根本走不到你处理ResponseEntity的逻辑。这是因为Feign默认的ErrorDecoder会把所有非2xx响应转换成异常抛出,哪怕你声明了返回ResponseEntity。

下面给你两种可行的解决方案,你可以根据自己的场景选择:


方案一:自定义ErrorDecoder适配ResponseEntity返回类型

我们可以写一个自定义的ErrorDecoder,让它判断当前调用的Feign方法是否返回ResponseEntity,如果是,就把响应交给ResponseEntityDecoder处理,最终返回包含错误状态码的ResponseEntity,而不是抛出异常。

步骤1:修改FeignClient的配置类

在你的OauthFeignClient.Conf类中,注入ObjectFactory<HttpMessageConverters>并添加自定义ErrorDecoder的Bean:

@Configuration
class Conf {
    @Value("${oauth.client.password}")
    String oauthClientPassword;

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public Encoder feignFormEncoder() {
        return new SpringFormEncoder();
    }

    @Bean
    public Contract feignContract() {
        return new SpringMvcContract();
    }

    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("web-client", oauthClientPassword);
    }

    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomResponseEntityErrorDecoder(messageConverters);
    }
}

步骤2:实现自定义ErrorDecoder

添加一个静态内部类,处理ResponseEntity类型的方法:

static class CustomResponseEntityErrorDecoder implements ErrorDecoder {
    private final ErrorDecoder defaultErrorDecoder = new ErrorDecoder.Default();
    private final ResponseEntityDecoder responseEntityDecoder;

    public CustomResponseEntityErrorDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
        this.responseEntityDecoder = new ResponseEntityDecoder(new SpringDecoder(messageConverters));
    }

    @Override
    public Exception decode(String methodKey, Response response) {
        try {
            // 解析当前Feign方法的元数据,获取返回类型
            MethodMetadata metadata = MethodMetadata.parse(Feign.configKey(OauthFeignClient.class, methodKey));
            Method method = metadata.method();
            Type returnType = method.getGenericReturnType();

            // 判断返回类型是否是ResponseEntity
            if (returnType instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) returnType;
                if (ResponseEntity.class.equals(parameterizedType.getRawType())) {
                    // 用ResponseEntityDecoder解析响应,确保能封装成ResponseEntity
                    responseEntityDecoder.decode(response, returnType);
                    // 返回包含原始响应的FeignException,让Spring的解码器最终转换成ResponseEntity
                    return FeignException.errorStatus(methodKey, response);
                }
            }
        } catch (IOException e) {
            // 解析失败时,交给默认ErrorDecoder处理
            return defaultErrorDecoder.decode(methodKey, response);
        }
        // 非ResponseEntity类型的方法,沿用默认异常处理逻辑
        return defaultErrorDecoder.decode(methodKey, response);
    }
}

方案二:升级Spring Cloud版本(更简单)

如果你的Spring Cloud版本比较旧(比如低于2020.0.x系列),可能存在ResponseEntity返回类型处理不完善的问题。升级到较新的版本(如2020.0.x或更高)后,默认情况下,返回ResponseEntity的Feign方法会自动返回包含非2xx状态码的ResponseEntity对象,不需要额外配置ErrorDecoder。

不过要注意:如果服务端返回的400响应格式不符合你produces指定的application/json,解码器可能还是会抛出异常,这时你需要调整produces属性,或者在自定义ErrorDecoder中兼容这种情况。


内容的提问来源于stack exchange,提问作者ch4mp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:24:40