SpringCloudFeign 全局异常处理

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

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

@Slf4j
@RestControllerAdvice
public class ExceptionHandle {

    @ExceptionHandler(Exception.class)
    private Result handle(Exception exception) {
        return null;
    }
}

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


@Slf4j
@RestControllerAdvice({"com.test.controller"})
//@RestControllerAdvice
public class ExceptionHandle {
}

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

异常信息例如:

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

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

feign:
  hystrix:
    enabled: false

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

@Slf4j
@Configuration
public class ExceptionErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String var1, Response response) {
        try {
            if (response.body() != null) {
                String body = Util.toString(response.body().asReader());
                log.error(body);
                ExceptionInfo exceptionInfo = JSON.parseObject(body, new TypeReference<ExceptionInfo>() {
                });
               // Class clazz = Class.forName(exceptionInfo.getException());
                //Exception  exception = (Exception) clazz.getDeclaredConstructor(String.class).newInstance(exceptionInfo.getMessage());
                return new HystrixBadRequestException(exceptionInfo.getMessage());
                //return exception;
            }
        } catch (Exception var4) {
            log.error(var4.getMessage());
            return new InternalException(var4.getMessage());
        }
        return new InternalException("system error");
    }
}

ExceptionInfo 类

@Data
public class ExceptionInfo {

    private Long timestamp;

    private Integer status;

    private String exception;

    private String message;

    private String path;

    private String error;
}

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

public class KeepErrMsgConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new UserErrorDecoder();
    }
    /**
     * 自定义错误
     */
    public class UserErrorDecoder implements ErrorDecoder {

        private Logger logger = LoggerFactory.getLogger(getClass());

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

不进入熔断:


public class NotBreakerConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new UserErrorDecoder();
    }
    /**
     * 自定义错误
     */
    public class UserErrorDecoder implements ErrorDecoder {

        private Logger logger = LoggerFactory.getLogger(getClass());

        @Override
        public Exception decode(String methodKey, Response response) {
            Exception exception = null;
            try {
                String json = Util.toString(response.body().asReader());
                exception = new RuntimeException(json);
                // 将返回内容反序列化为Result,这里应根据自身项目作修改
                Result result = JSONObject.parseObject(json, Result.class);
                // 业务异常抛出简单的 RuntimeException,保留原来错误信息
                if (!ResultUtil.isSuccess(result)) {
                    exception = new HystrixBadRequestException(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)
    @Component
    interface WxServiceApi {

 
    }

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

参考:

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

你可能感兴趣的:(SpringBoot,Java,java,spring,boot)