异常信息形如:
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;
@Configuration
public class FeignErrorDecoder implements ErrorDecoder {
@Override
public 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 = 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 = 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.
第三方调用者抛出的异常:HystrixRuntimeException
一检查我们系统确实没有指定fallback和configuration,并且调用方开启了feign.hystrix.enabled: true
@FeignClient(value = "taxplan-workflow")
修改方法:
第三方调用在Application.java添加处理Feign异常的全局处理方法
@Bean
public Feign.Builder feignBuilder() {
return Feign.builder().requestInterceptor(new RequestInterceptor() {
@Override
public void apply(RequestTemplate requestTemplate) {
Map<String, String> 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调用全局异常处理解决方案
- Author -
筱进GG声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@