Feign调用全局异常处理解决方案

异常信息形如:

TestService#addRecord(ParamVO) failed and no fallback available.;
对于failed and no fallback available.这种异常信息,是因为项目开启了熔断:
feign.hystrix.enabled: true

当调用服务时抛出了异常,却没有定义fallback方法,就会抛出上述异常。由此引出了第一个解决方式。
解决方案: 自定义Feign解析器:
import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.crecgec.baseboot.jsoncore.exception.BaseException; import feign.Response; import feign.Util; import feign.codec.ErrorDecoder; import org.springframework.context.annotation.Configuration; import java.io.IOException; @Configurationpublic class FeignErrorDecoder implements ErrorDecoder {@Overridepublic Exception decode(String methodKey, Response response) {try {// 这里直接拿到我们抛出的异常信息String message = Util.toString(response.body().asReader()); try {JSONObject jsonObject = JSONObject.parseObject(message); return new BaseException(jsonObject.getString("resultMsg"), jsonObject.getInteger("resultCode")); } catch (JSONException e) {e.printStackTrace(); }} catch (IOException ignored) {}return decode(methodKey, response); }}

定义系统的异常类
public class BaseException extends RuntimeException {private int status ; public int getStatus() {return status; } public void setStatus(int status) {this.status = status; } public BaseException() {} public BaseException(String message, int status) {super(message); this.status = status; } public BaseException(String message) {super(message); } public BaseException(String message, Throwable cause) {super(message, cause); } public BaseException(Throwable cause) {super(cause); } public BaseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace); }}

统一异常拦截转换对应的异常信息返回前端
public class ResultSet {/*** 返回的状态码*/private Integer resultCode; /*** 返回的消息*/private String resultMsg; /*** 返回的数据*/private Object data; public ResultSet() {}public ResultSet(Integer resultCode, String resultMsg) {this.resultCode = resultCode; this.resultMsg = resultMsg; }public ResultSet(Integer resultCode, String resultMsg, Object data) {this.resultCode = resultCode; this.resultMsg = resultMsg; this.data = https://www.it610.com/article/data; }public Integer getResultCode() {return resultCode; }public void setResultCode(Integer resultCode) {this.resultCode = resultCode; }public String getResultMsg() {return resultMsg; }public void setResultMsg(String resultMsg) {this.resultMsg = resultMsg; }public Object getData() {return data; }public void setData(Object data) {this.data = data; }}

全局异常类处理配置:
@ExceptionHandler(value = https://www.it610.com/article/BaseException.class)public ResultSet defaultErrorHandler(HttpServletRequest req, HttpServletResponse resp, BaseException e) {ResultSet resultSet = new ResultSet(); if (e.getStatus() == 400) {resultSet.setResultCode(-1); resultSet.setResultMsg(e.getMessage()); resultSet.setData(null); resp.setStatus(400); } else {resp.setStatus(500); if(logger.isErrorEnabled()){logger.error("系统异常,请联系系统开发人员进行处理", e); }resultSet.setResultCode(-1); resultSet.setResultMsg(e.getMessage()); resultSet.setData(null); }return resultSet; }

这样就能完成了feign接收异常处理的自定义异常信息!
统一处理@FeignClient调用接口异常----原样抛出 第三方系统调用我方系统@FeignClient接口时报错
com.netflix.hystrix.exception.HystrixRuntimeException: WorkFlowTaskOperateService#processWorkFlowTaskSyncCallback(TaskProcessDTO) failed and no fallback available.
我方系统出现FeignException.
Feign调用全局异常处理解决方案
文章图片

第三方调用者抛出的异常:HystrixRuntimeException
Feign调用全局异常处理解决方案
文章图片

一检查我们系统确实没有指定fallback和configuration,并且调用方开启了feign.hystrix.enabled: true
@FeignClient(value = "https://www.it610.com/article/taxplan-workflow")

修改方法:
第三方调用在Application.java添加处理Feign异常的全局处理方法
@Beanpublic Feign.Builder feignBuilder() {return Feign.builder().requestInterceptor(new RequestInterceptor() {@Overridepublic void apply(RequestTemplate requestTemplate) {Map customHeaders = WebUtils.getCustomHeaders(); customHeaders.forEach((k, v) -> {requestTemplate.header(k, v); }); }}).errorDecoder(new CustomErrorDecoder()); }

这里使用了RequestInterceptor拦截器,可以定制请求头,如果不想定制,可以改为
return Feign.builder().errorDecoder(new CustomErrorDecoder());

实现ErrorDecoder接口,其中ExceptionCode是枚举类.
public Exception decode(String methodKey, Response response) {if (response.status() >= 400 && response.status() <= 499) {return new BaseBizException(ExceptionCode.CALL_INNER_ERROR, "Client error.httpStatusCode:" + response.status()); } else {if (response.status() >= 500 && response.status() <= 599 && response.body() != null) {try {String content = CharStreams.toString(new InputStreamReader(response.body().asInputStream(), StandardCharsets.UTF_8)); Map responseBody = (Map) JSONObject.parseObject(content, Map.class); if (responseBody.containsKey("code")) {return new BaseBizException(responseBody.get("code").toString(), Objects.toString(responseBody.get("msg"))); }} catch (Exception var5) {}} return new BaseBizException(ExceptionCode.CALL_INNER_ERROR); }}

ExceptionCode枚举类如下:可以自定义增加删除
public enum ExceptionCode {ILLEGAL_STATE(4001, "非法访问"),PARAM_REQUIRED(4002, "参数不能为空"),PARAM_FORMAT_ILLEGAL(4003, "参数格式错误"),REQUEST_DATA_DUPLICATION(4004, "重复请求"),REQUEST_DATA_ERROR(4005, "请求数据错误"),REQUEST_DATA_NOT_MATCH(4006, "请求数据不一致"),RECORD_NOT_EXIST(5001, "记录不存在"),RECORD_EXISTED(5002, "记录已存在"),RECORD_ILLEGAL_STATE(5003, "数据异常"),BALANCE_NOT_ENOUGH(5103, "余额不足"),CALL_INNER_ERROR(5800, "调用内部服务接口异常"),THIRD_PART_ERROR(5801, "调用第三方接口异常"),SYSTEM_ERROR(9999, "系统异常"); public final int code; public final String defaultMessage; private ExceptionCode(int code, String defaultMessage) {this.code = code; this.defaultMessage = defaultMessage; }}

【Feign调用全局异常处理解决方案】以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

    推荐阅读