SpringCloudFeign 全局异常处理

2022-08-09 14:09:18

坑一:服务端使用全局拦截异常统一处理,客户端未能捕获到异常

服务端中,使用了全局拦截异常统一处理(@RestControllerAdvice),返回统一格式信息,导致feign客户端调用服务端时候,当服务端出现异常,客户端捕获不到异常,也未能进入熔断,降级

@Slf4j@RestControllerAdvicepublicclassExceptionHandle{@ExceptionHandler(Exception.class)private Resulthandle(Exception exception){return null;}}

解决办法:@RestControllerAdvice 注解中指定 需要统一拦截异常包 ,feign 调用 包路径不包括在内

@Slf4j@RestControllerAdvice({"com.test.controller"})//@RestControllerAdvicepublicclassExceptionHandle{}

坑二:feign开启熔断后,获取不到服务提供方抛出的原始异常信息

异常信息例如:

WxServiceApi#getTokenByAppId(String) failed and no fallback available.

预期目标:获取原始异常信息返回
解决办法一:关闭熔断

feign:hystrix:enabled:false

解决办法二:实现ErrorDecoder ,使用自定义ErrorDecoder
ErrorDecoder 可以全局,也可以在 @FeignClient 中指定
全局:不进入熔断

@Slf4j@ConfigurationpublicclassExceptionErrorDecoderimplementsErrorDecoder{@Overridepublic Exceptiondecode(String var1, Response response){try{if(response.body()!= null){
                String body= Util.toString(response.body().asReader());
                log.error(body);
                ExceptionInfo exceptionInfo= JSON.parseObject(body,newTypeReference<ExceptionInfo>(){});// Class clazz = Class.forName(exceptionInfo.getException());//Exception  exception = (Exception) clazz.getDeclaredConstructor(String.class).newInstance(exceptionInfo.getMessage());returnnewHystrixBadRequestException(exceptionInfo.getMessage());//return exception;}}catch(Exception var4){
            log.error(var4.getMessage());returnnewInternalException(var4.getMessage());}returnnewInternalException("system error");}}

ExceptionInfo 类

@DatapublicclassExceptionInfo{private Long timestamp;private Integer status;private String exception;private String message;private String path;private String error;}

单个@FeignClient 中指定
进入熔断:

publicclassKeepErrMsgConfiguration{@Beanpublic ErrorDecodererrorDecoder(){returnnewUserErrorDecoder();}/**
     * 自定义错误
     */publicclassUserErrorDecoderimplementsErrorDecoder{private Logger logger= LoggerFactory.getLogger(getClass());@Overridepublic Exceptiondecode(String methodKey, Response response){
            Exception exception= null;try{// 获取原始的返回内容
                String json= Util.toString(response.body().asReader());
                exception=newRuntimeException(json);// 将返回内容反序列化为Result,这里应根据自身项目作修改
                Result result= JSONObject.parseObject(json, Result.class);// 业务异常抛出简单的 RuntimeException,保留原来错误信息if(!ResultUtil.isSuccess(result)){
                    exception=newRuntimeException(result.getObj().toString());}}catch(IOException ex){
                logger.error(ex.getMessage(), ex);}return exception;}}}

不进入熔断:

publicclassNotBreakerConfiguration{@Beanpublic ErrorDecodererrorDecoder(){returnnewUserErrorDecoder();}/**
     * 自定义错误
     */publicclassUserErrorDecoderimplementsErrorDecoder{private Logger logger= LoggerFactory.getLogger(getClass());@Overridepublic Exceptiondecode(String methodKey, Response response){
            Exception exception= null;try{
                String json= Util.toString(response.body().asReader());
                exception=newRuntimeException(json);// 将返回内容反序列化为Result,这里应根据自身项目作修改
                Result result= JSONObject.parseObject(json, Result.class);// 业务异常抛出简单的 RuntimeException,保留原来错误信息if(!ResultUtil.isSuccess(result)){
                    exception=newHystrixBadRequestException(result.getObj().toString());}}catch(IOException ex){
                logger.error(ex.getMessage(), ex);}return exception;}}}

@FeignClient 注解配置

@FeignClient(name="wx-service",url="http://localhost:8082", fallbackFactory= WxHystrixClientFallbackFactory.class, configuration= NotBreakerConfiguration.class)@ComponentinterfaceWxServiceApi{}

根据自身项目,来实现所需要的errorDecoder配置,灵活使用

参考:

https://blog.csdn.net/hnhygkx/article/details/89492031

  • 作者:青菜12131
  • 原文链接:https://blog.csdn.net/qq_36174487/article/details/104952399
    更新时间:2022-08-09 14:09:18