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


Posted in Java/Android onJune 24, 2021

异常信息形如:

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.

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

第三方调用者抛出的异常:HystrixRuntimeException

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

一检查我们系统确实没有指定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;
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
springboot利用redis、Redisson处理并发问题的操作
Jun 18 Java/Android
springboot如何初始化执行sql语句
Jun 22 Java/Android
Maven学习----Maven安装与环境变量配置教程
Jun 29 Java/Android
jackson json序列化实现首字母大写,第二个字母需小写
Jun 29 Java/Android
Java使用httpRequest+Jsoup爬取红蓝球号码
Jul 02 Java/Android
一篇文章带你学习Mybatis-Plus(新手入门)
Aug 02 Java/Android
Java 关于String字符串原理上的问题
Apr 07 Java/Android
Android开发之WECHAT微信小程序路由跳转的两种形式
Apr 12 Java/Android
IDEA 2022 Translation 未知错误 翻译文档失败
Apr 24 Java/Android
Spring Data JPA框架持久化存储数据到数据库
Apr 28 Java/Android
JAVA springCloud项目搭建流程
May 11 Java/Android
Java+swing实现抖音上的表白程序详解
Jun 25 Java/Android
总结一下关于在Java8中使用stream流踩过的一些坑
IDEA使用SpringAssistant插件创建SpringCloud项目
使用feign服务调用添加Header参数
详解Java实现数据结构之并查集
解决SpringCloud Feign传对象参数调用失败的问题
Jun 23 #Java/Android
详解Java实现设计模式之责任链模式
Jun 23 #Java/Android
Spring boot应用启动后首次访问很慢的解决方案
You might like
php数组索引的Key加引号和不加引号的区别
2014/08/19 PHP
WordPress主题制作之模板文件的引入方法
2015/12/28 PHP
PHP中的self关键字详解
2019/06/23 PHP
layui数据表格自定义每页条数limit设置
2019/10/26 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
2020/04/02 PHP
jquery下jstree简单应用 - v1.0
2011/04/14 Javascript
JS实现标签页效果(配合css)
2013/04/03 Javascript
jQuery实现仿QQ头像闪烁效果的文字闪动提示代码
2015/11/03 Javascript
为什么JavaScript没有块级作用域
2016/05/22 Javascript
jQuery如何封装输入框插件
2016/08/19 Javascript
JS中的phototype详解
2017/02/04 Javascript
解决Nuxt使用axios跨域问题
2020/07/06 Javascript
JS性能优化实现方法及优点进行
2020/08/30 Javascript
详解JavaScript的this指向和绑定
2020/09/08 Javascript
JavaScript 生成唯一ID的几种方式
2021/02/19 Javascript
[01:30:15]DOTA2-DPC中国联赛 正赛 Ehome vs Aster BO3 第二场 2月2日
2021/03/11 DOTA
Python写的PHPMyAdmin暴力破解工具代码
2014/08/06 Python
Python StringIO模块实现在内存缓冲区中读写数据
2015/04/08 Python
使用Python操作Elasticsearch数据索引的教程
2015/04/08 Python
Python+Pika+RabbitMQ环境部署及实现工作队列的实例教程
2016/06/29 Python
python使用matplotlib绘图时图例显示问题的解决
2017/04/27 Python
100行Python代码实现自动抢火车票(附源码)
2018/01/11 Python
python中正则表达式的使用方法
2018/02/25 Python
Django CSRF跨站请求伪造防护过程解析
2019/07/31 Python
详解PyQt5中textBrowser显示print语句输出的简单方法
2020/08/07 Python
pyx文件 生成pyd 文件用于 cython调用的实现
2021/03/04 Python
HTML5之SVG 2D入门4—笔画与填充
2013/01/30 HTML / CSS
英国户外服装品牌:Craghoppers
2019/04/25 全球购物
C/C++ 笔试、面试题目大汇总
2015/11/21 面试题
金士达面试非笔试
2012/03/14 面试题
学生打架检讨书1000字
2014/01/16 职场文书
出国英文推荐信
2014/05/10 职场文书
中国文明网向国旗敬礼活动精彩寄语2014
2014/09/27 职场文书
文明上网主题班会
2015/08/14 职场文书
python开发实时可视化仪表盘的示例
2021/05/07 Python
python3.7.2 tkinter entry框限定输入数字的操作
2021/05/22 Python