spring 假装客户端异常处理
spring feign client exception handling
我有一些 fiegn 客户端发送请求到其他微服务。
@FeignClient(name="userservice")
public interface UserClient {
@RequestMapping(
method= RequestMethod.GET,
path = "/userlist")
String getUserByid(@RequestParam(value ="id") String id);
}
现在我发送这样的请求
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);
}
这里的问题是,如果发生任何 FeignException,我不会收到任何错误代码。
我需要在其他 APIS 中发送相应的错误代码以发送给调用方
那么如何提取错误码呢?我想提取错误代码并构建一个 responseEntity
我得到了 this 代码,但不知道如何在我的函数中使用它。
您是否尝试在假装客户端上实施 FallbackFactory?
在创建方法中,在 return 之前,您可以使用以下代码片段检索 http 状态代码:
String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";
示例:
@FeignClient(name="userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
@RequestMapping(
method= RequestMethod.GET,
path = "/userlist")
String getUserByid(@RequestParam(value ="id") String id);
}
@Component
static class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";
return new UserClient() {
@Override
public String getUserByid() {
logger.error(httpStatus);
// what you want to answer back (logger, exception catch by a ControllerAdvice, etc)
}
};
}
}
不是同一个问题,但这对我的情况有所帮助。
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";
}
}
此示例使 Spring return 与您收到的 HTTP 状态相同
有一个 ErrorDecored 接口,就像 documentation
中所说的那样
上面关于 FallbackFactory 的答案是可行的,但属于其他抽象层。
我要迟到了,但这是我的 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");
}
}
}
Return @Bean
以上 class 在 FeignClientConfiguration
class.
public class MyFeignClientConfiguration {
@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}
}
将此用作 FeignClient 的配置 class。
@FeignClient(value = "myFeignClient", configuration = MyFeignClientConfiguration.class)
然后你可以使用GlobalExceptionHandler
.
来处理这些异常
我也有点晚了,但我想确保您也检查其他可能的解决方案。
Feign with Spring 处理异常的方式非常糟糕,因此我想出了一个自定义解决方案,它创建了一个强大的环境来按照您想要的方式定义业务异常。
它利用注册到 Feign 客户端的自定义 ErrorDecoder
,并增加了根据方法或 class 级别自定义异常处理的可能性。
查看:Maintainable error handling with Feign clients? Not a dream anymore
我有一些 fiegn 客户端发送请求到其他微服务。
@FeignClient(name="userservice")
public interface UserClient {
@RequestMapping(
method= RequestMethod.GET,
path = "/userlist")
String getUserByid(@RequestParam(value ="id") String id);
}
现在我发送这样的请求
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);
}
这里的问题是,如果发生任何 FeignException,我不会收到任何错误代码。
我需要在其他 APIS 中发送相应的错误代码以发送给调用方
那么如何提取错误码呢?我想提取错误代码并构建一个 responseEntity
我得到了 this 代码,但不知道如何在我的函数中使用它。
您是否尝试在假装客户端上实施 FallbackFactory?
在创建方法中,在 return 之前,您可以使用以下代码片段检索 http 状态代码:
String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";
示例:
@FeignClient(name="userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
@RequestMapping(
method= RequestMethod.GET,
path = "/userlist")
String getUserByid(@RequestParam(value ="id") String id);
}
@Component
static class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
String httpStatus = cause instanceof FeignException ? Integer.toString(((FeignException) cause).status()) : "";
return new UserClient() {
@Override
public String getUserByid() {
logger.error(httpStatus);
// what you want to answer back (logger, exception catch by a ControllerAdvice, etc)
}
};
}
}
不是同一个问题,但这对我的情况有所帮助。 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";
}
}
此示例使 Spring return 与您收到的 HTTP 状态相同
有一个 ErrorDecored 接口,就像 documentation
中所说的那样上面关于 FallbackFactory 的答案是可行的,但属于其他抽象层。
我要迟到了,但这是我的 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");
}
}
}
Return @Bean
以上 class 在 FeignClientConfiguration
class.
public class MyFeignClientConfiguration {
@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}
}
将此用作 FeignClient 的配置 class。
@FeignClient(value = "myFeignClient", configuration = MyFeignClientConfiguration.class)
然后你可以使用GlobalExceptionHandler
.
我也有点晚了,但我想确保您也检查其他可能的解决方案。
Feign with Spring 处理异常的方式非常糟糕,因此我想出了一个自定义解决方案,它创建了一个强大的环境来按照您想要的方式定义业务异常。
它利用注册到 Feign 客户端的自定义 ErrorDecoder
,并增加了根据方法或 class 级别自定义异常处理的可能性。
查看:Maintainable error handling with Feign clients? Not a dream anymore