当前位置: 首页 > news >正文

异常重试_从零搭建后端框架——异常统一处理的三种方式

前言

项目在运行时出现异常时,如若没有对异常进行捕获并处理,就会出现如下页面:

148958cf602432799e2a451f215ea75f.png

这样显然对用户是极其不友好的。

后端不应该直接返回错误页面,而应返回统一的错误信息,比如:

{
  "code": 500,
  "data": null,
  "message": "服务异常,请稍后重试"
}
复制代码

然后,前端根据返回的信息,显示友好的提示页面。

Spring提供了三种方式对异常统一处理:

  1. @ExceptionHandler
  2. 实现HandlerExceptionResolver接口
  3. @ControllerAdvice + @ExceptionHandler

下面我们来实际操作下。

具体实现

@ExceptionHandler

在【统一基类、接口、返回对象设计】这一篇文章中, 定义了Controller的基类BaseController,所以只要在BaseController中使用@ExceptionHandler处理异常, 其它Controller继承BaseController即可。实现如下:

@Slf4j
public abstract class BaseController {

    /**
     * BusinessException 异常处理
     */
    @ResponseBody
    @ExceptionHandler(BusinessException.class)
    public ApiResult businessExceptionHandler(BusinessException e) {
        log.error(e.getMessage(), e);
        // do something
        return ApiResult.fail(e.getMessage());
    }

    /**
     * Exception 异常处理
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ApiResult exceptionHandler(Exception e) {
        log.error(e.getMessage(), e);
        return ApiResult.fail("服务异常,请稍后重试");
    }
}
复制代码

这里对异常BusinessException和Exception进行了处理, BusinessException是约定的业务异常的基类,若是主动抛出一般都要求是BusinessException的子类,都会被businessExceptionHandler处理。 若是其它异常,可能是意想不到的异常,则会被exceptionHandler处理。

统一处理后,返回结果如下:

567d1c03bc00f30d91ba27ce67dff687.png

实现HandlerExceptionResolver接口

@Slf4j
@Component
public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
        log.error(e.getMessage(), e);
        ApiResult apiResult;
        if (e instanceof BusinessException) {
            BusinessException be = (BusinessException) e;
            // do something
            apiResult = ApiResult.fail(be.getMessage());
        } else {
            apiResult = ApiResult.fail("服务异常,请稍后重试");
        }
        WebUtils.writeJson(response, apiResult);
        return null;
    }
}
复制代码

该方式需要实现HandlerExceptionResolver接口,然后将实现类注入到Spring容器中。

但第一种方式中,通过@ResponseBody注解,Spring就帮我们返回了json格式数据,而这需要自己实现。

这里实现了工具类WebUtils,用于返回json数据,如下:

public class WebUtils {

    private static final Logger log = LoggerFactory.getLogger(WebUtils.class);

    private static Gson gson = new GsonBuilder().serializeNulls().create();

    /**
     * 返回json数据
     *
     * @param response
     * @param object
     */
    public static void writeJson(HttpServletResponse response, int status, Object object) {
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(status);
        PrintWriter out = null;
        try {
            String data = object instanceof String ? (String) object : gson.toJson(object);
            out = response.getWriter();
            out.print(data);
            out.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * 返回json数据
     *
     * @param response
     * @param object
     */
    public static void writeJson(HttpServletResponse response, Object object) {
        writeJson(response, HttpServletResponse.SC_OK, object);
    }

    /**
     * 返回json数据
     *
     * @param response
     * @param object
     */
    public static void writeJson(ServletResponse response, Object object) {
        if (response instanceof HttpServletResponse) {
            writeJson((HttpServletResponse) response, object);
        }
    }
}
复制代码

工具类中使用了Gson,需要引用:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
</dependency>
复制代码

@ControllerAdvice + @ExceptionHandler

该方式与第一种方式类似,如下:

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * BusinessException 异常处理
     */
    @ResponseBody
    @ExceptionHandler(BusinessException.class)
    public ApiResult businessExceptionHandler(BusinessException e) {
        log.error(e.getMessage(), e);
        // do something
        return ApiResult.fail(e.getMessage());
    }

    /**
     * Exception 异常处理
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ApiResult exceptionHandler(Exception e) {
        log.error(e.getMessage(), e);
        return ApiResult.fail("服务异常,请稍后重试");
    }
}
复制代码

总结

三种方式都能很好对异常进行统一处理,但是一般推荐使用@ControllerAdvice + @ExceptionHandler方式, 这样能够使异常处理与业务逻辑分离,并且不用自己处理Json数据返回。

源码

http://github.com/zhuqianchan…

相关文章:

  • js截取视频第一帧_短视频如何截取生成GIF?干货分享,大神手把手教你制作GIF动图...
  • 回顾一年的工作历程_ABM2020回顾|我们做过什么(一)
  • 通过改变网络拓扑使用Sniffer Pro监控、分析协议的示意图
  • python locust api_Locust API 文档
  • 暴走后清醒(2006版)
  • sceneflow 数据集多少张图片_快速使用 Tensorflow 读取 7 万数据集!
  • Google Talk Java手机客户端
  • grafa导出数据图标_有这些图表美化工具,十分钟配出炫酷的数据可视化大屏
  • 书脊开胶了用什么胶粘_使用方便快捷的防水快干胶时,要注意些什么呢?
  • 8月22讲课记录
  • 使用智能指针错误导致内存泄漏_第24篇-戏说C++ 内存泄漏(B)
  • 不知多少Java程序员能解答这个问题!
  • 回填用土好还是砂石料好_砂石土的一般配比
  • 钢铁中的生命,我们所不知道的柱子和他的朋友们!
  • 动态服务器值 回放报错 没有关联到_LR关联(带附件) - 缺1份淡定ㄣ - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 77. Combinations
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • css选择器
  • Java基本数据类型之Number
  • Java知识点总结(JavaIO-打印流)
  • markdown编辑器简评
  • sessionStorage和localStorage
  • Twitter赢在开放,三年创造奇迹
  • VUE es6技巧写法(持续更新中~~~)
  • 当SetTimeout遇到了字符串
  • 记一次用 NodeJs 实现模拟登录的思路
  • 将回调地狱按在地上摩擦的Promise
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 软件开发学习的5大技巧,你知道吗?
  • 算法系列——算法入门之递归分而治之思想的实现
  • 一些关于Rust在2019年的思考
  • 云大使推广中的常见热门问题
  • 在Docker Swarm上部署Apache Storm:第1部分
  • (007)XHTML文档之标题——h1~h6
  • (31)对象的克隆
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (待修改)PyG安装步骤
  • (多级缓存)缓存同步
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (三)c52学习之旅-点亮LED灯
  • (算法)求1到1亿间的质数或素数
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET 中 GetProcess 相关方法的性能
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • // an array of int
  • @entity 不限字节长度的类型_一文读懂Redis常见对象类型的底层数据结构
  • [20170713] 无法访问SQL Server
  • [3D基础]理解计算机3D图形学中的坐标系变换
  • [AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯
  • [APUE]进程关系(下)
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现
  • [BT]BUUCTF刷题第8天(3.26)