spring feign 客户端异常处理

kpc*_*der 12 exception spring-cloud-feign feign

我有一些 fiegn 客户端发送请求其他微服务。

@FeignClient(name="userservice")
public interface UserClient {

    @RequestMapping(
            method= RequestMethod.GET,
                      path = "/userlist")
    String getUserByid(@RequestParam(value ="id") String id);

}
Run Code Online (Sandbox Code Playgroud)

现在我正在发送这样的请求

try {
    String responseData = userClient.getUserByid(id);
    return responseData;
    }

catch(FeignException e)
 {
 logger.error("Failed to get user", id);
}

catch (Exception e) 
{
 logger.error("Failed to get user", id);
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是,如果发生任何 FeignException,我不会收到任何错误代码。

我需要在其他 APIS 中发送相应的错误代码以发送给调用方

那么如何提取错误代码呢?我想提取错误代码并构建一个 responseEntity

我得到了这段代码,但不知道如何在我的函数中使用。

小智 9

不是同一个问题,但这对我的情况有所帮助。OpenFeign 的 FeignException 不绑定到特定的 HTTP 状态(即不使用 Spring 的 @ResponseStatus 注释),这使得 Spring 在遇到 FeignException 时默认为 500。没关系,因为 FeignException 可能有许多与特定 HTTP 状态无关的原因。

但是,您可以更改 Spring 处理 FeignExceptions 的方式。只需定义一个处理 FeignException 的 ExceptionHandler

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(FeignException.class)
    public String handleFeignStatusException(FeignException e, HttpServletResponse response) {
        response.setStatus(e.status());
        return "feignError";
    }

}
Run Code Online (Sandbox Code Playgroud)

此示例使 Spring 返回您收到的相同 HTTP 状态

  • 尽管这有效,但它却促进了一种不良实践,即向堆栈泄漏低级实现细节。FeignClient 在应用层中使用,为域提供一些值,它与传输层(即控制器、http 法规等)无关。如果您想这样做,我建议首先将“FeignException”包装到适当的域中,例如“UserNotFoundException”,然后才使用您在后者上提出的方法。 (6认同)

rph*_*lmr 6

您是否尝试在您的假客户端上实现 FallbackFactory ?

https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html#spring-cloud-feign-hystrix-fallback

在 create 方法上,在返回之前,您可以使用以下代码片段检索 http 状态代码:

String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";
Run Code Online (Sandbox Code Playgroud)

示例:

String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";
Run Code Online (Sandbox Code Playgroud)

  • 异常,女巫已被扔进后备工厂,不会被控制器建议捕获 (3认同)
  • 在一般情况下,控制器中会有多种方法,所以我们是否继续实现每个方法,即使我只想处理少数方法而不是全部 (2认同)

Vai*_*ibS 5

我迟到了,但这是我的 2 美分。我们有相同的用例来处理基于错误代码的异常,我们使用custom ErrorDecoder.

public class CustomErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        String requestUrl = response.request().url();
        Response.Body responseBody = response.body();
        HttpStatus responseStatus = HttpStatus.valueOf(response.status());

        if (responseStatus.is5xxServerError()) {
            return new RestApiServerException(requestUrl, responseBody);
        } else if (responseStatus.is4xxClientError()) {
            return new RestApiClientException(requestUrl, responseBody);
        } else {
            return new Exception("Generic exception");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

@BeanFeignClientConfiguration课堂上返回上述课程。

public class MyFeignClientConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}
Run Code Online (Sandbox Code Playgroud)

将此用作 FeignClient 的配置类。

@FeignClient(value = "myFeignClient", configuration = MyFeignClientConfiguration.class)
Run Code Online (Sandbox Code Playgroud)

然后您可以使用GlobalExceptionHandler.

  • 您可以在“MyFeignClientConfiguration”上删除“@Configuration”,因为该类是通过“configuration = MyFeignClientConfiguration.class”实例化的。 (2认同)

gal*_*ics 5

我也有点晚了,但我想确保您也检查其他潜在的解决方案。

Feign with Spring 处理异常的方式是出了名的糟糕,所以我想出了一个自定义解决方案,它创建了这个强大的环境,以您想要的方式定义业务异常。

它利用ErrorDecoder注册到 Feign 客户端的自定义,并增加了根据方法或类级别自定义异常处理的可能性。

看看:Feign 客户端的可维护错误处理?不再是梦