人世仙家本自殊,何须相见向中途。惊鸿瞥过游龙去,漫恼陈王一事无。
嗨,大家好,我是洛神,性别男。一个来自快乐星球的程序员。
欢迎大家专注我的公众号【程序员洛神】,不仅分享技术,还会分享生活趣事、体育。

前言

前几天闲来无事看之前的项目,发现项目中对异常问题的处理非常不优雅,有些接口中为了处理异常使用的trycatch语句占用了一半的代码,读起来灰常头疼,所以阿洛就用一招武林中失传已久的《全局异常捕获大法》一顿输出,处理完后的代码逻辑结构看起来很是清晰,优雅的yaPi~

啥是全局异常捕获?

全局异常捕获就是定一个全局异常捕获类(通常都是使用Spring自带的增强注解@ControllerAdvice),所有抛出的异常都会被捕获到(这个地方不严谨,应该是根据ExceptionHanler中定义的捕获范围来确定),然后根据捕获类中的处理逻辑对异常进行处理(一般都是返回前端一个封装好的实体类,里面包含msg,code等信息)。

说到这里了,阿洛就顺便带大家复习下异常相关的内容:

先看下异常类的大家庭(RunTimeException的子类太多,没有全部查出来,只找了几个常见的异常类,重点看整体结构关系)

Error大部分问题都是由于虚拟机问题造成的异常。这种问题是无法通过代码层面进行捕获或者处理的。

平时我们开发中打交道最多的就是Exception了,它具体分为RunTimeException(运行时异常)和IOException异常(其他异常)。
运行时异常我们是可以通过全局异常捕获来统一处理的,但是对于其他异常,Java是强制要求我们必须使用TryCatch或Throw来解决异常的(例如文件流处理啊,JDBC建立连接啊这些)

这里可能会有人急眼了,NND!好不容易学会了个全局异常捕获,结果这也不能用,那也不能用,劳资不学了!
(╯‵□′)╯︵┻━┻

别着急啊傻瓜,咱们这个全局异常捕获,本来就是用来处理运行时异常的问题的,因为大部分抛异常的情况都是运行时的异常。

为啥要用全局异常捕获处理?

全局异常捕获处理的好处有几个:
1.避免代码中出现大量的try catch,影响代码可读性。
2.减少重复开发代码量。

第一点我相信大家是可以理解的,因为我相信很多人都有被try catch折磨的经历,一个50行代码的接口,里面30行是try catch,自己看着糟心,review的时候领导起了杀心。用了全局异常捕获后,对于运行时的异常,我们不需要刻意的对代码进行异常处理,只需要在全局异常类中定义好相关的异常的处理逻辑,就可以放心的将异常抛出去了。

List lists = null;
System.out.println(lists.get(0));

这个代码如果正常运行,会出现什么,前端会直接返回一个nullPointerException,用户看见之后一脸懵逼。

为了良好的用户体验,初级开发工程师小张做了一下处理:

  List lists = null;try{System.out.println(lists.get(0));}catch (Exception e){MyRest myRest = new MyRest();myRest.setMsg("尊敬的用户,由于您不是VIP客户,无法调用该接口,请充值后重试");myRest.setHttpStatus(500);myRest.setIdentifier("-999");return myRest;}

运行结果:

吆西!不仅完美解决了异常处理问题,而且还给公司带来了收益,这代码提交上去,明天我是不是就得当leader了,我擦,我第一次当领导,是不是得上去讲点啥?要是员工们不服从,我该咋办啊。。。。

小张激动的在钉钉上跟领导说:领导,问题修复好了。 领导:嗯,对了,还有一个地方类似的问题,你也给修改一下吧,完事一块提交给我。

小张:这尼玛不是送分题吗,这次升职加薪稳了!

小张翘起二郎腿,找到问题所在地,看了下代码:

呵,原来是数组越界的问题,简简单单

完成!提交!
领导review代码后:很好,小张,你被解雇了。

欸嘿?为啥嘞?没啥毛病啊,正确处理了潜在的异常问题,为啥领导还解雇我,肯定是担心我哪天骑到他头上,哼

小张还没有意识到事情的严重性,问题是解决了,但是回头看一下代码呢

20+行的代码,真正的业务代码有多少?不到5行,剩下的15行都是为了处理这个异常,这只是举例,真实业务环境下,一个接口里如果牵扯到了多个业务交互,你不得整个几千行?多吓人,review的时候不用看别的了,光看try catch就中了。烦不烦。

小张被开除的根本原因,还是因为他把握不住,不够优雅,不懂得好好反思,耗子尾汁。
那么,既然小张的这种写法有问题,那么我们看看公司的顶级架构师是怎么优化这个问题的?


/**
*全局异常捕获类
@author 公司顶级架构师
@date  小张被开除的那一天
*/
@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)@ResponseBodypublic Rest handle(HttpServletRequest request, Exception e) {//这里是举例 所以代码简化//真实项目中,不建议使用魔法值,所有下面这种定义常量,建议使用枚举类处理String errMsg = "未知错误";String errCode = "-999";int httpStatus = 500;if(e instanceof NullPointerException){errMsg = "由于这个接口是顶级架构师开发的,所以VIP开通费用提高500元";}else if (e instanceof IndexOutOfBoundsException){errMsg = "由于这个接口是顶级架构师开发的,同样,升级超级VIP需要额外支付1000元";}else {errMsg = e.toString();}MyRest rest = new MyRest();rest.setIdentifier(errCode);rest.setHttpStatus(httpStatus);rest.setMsg(errMsg);return rest;}
}

欸嘿,看起来有点意思的感jio了,那么这么做之后的效果如何呢?


同样是这两个问题,我们看一下不用trycatch包裹,执行后的效果如何?



欸嘿,惊不惊喜?意不意外?满足了同样的要求,我的业务代码没有任何改变,这种操作就是类似于SpringAOP的思想,非业务侵入式功能,在不改变原有业务代码的情况下,对代码进行增强。炫酷吊炸天有木有。
而且,有没有发现,上面我提到的使用全局捕获异常的好处里的第二条:减少重复开发代码量,相信大家也看到很明白了把,我只需要定义一次返回的格式即可。

好了,看完了顶级架构师的代码了,我们来说下是如何实现这个功能的:

其实也没有神秘的地方,能实现这个功能,主要是依赖于Spring为我们提供的注解@ControllerAdvice+@ExceptionHandler

@ControllerAdvice的作用
1.全局异常处理
2.全局数据绑定
3.全局数据预处理

使用也很简单,我们只需要建立一个专门的异常捕获的类,然后在类上面加上注解@ControllerAdvice。
这个注解的意义就是告诉Spring,所有你管理的bean里,只要抛出异常了,没有被trycatch处理的,统统都交给我就中了。

然后我们需要定义一个处理异常的方法,在方法上加上注解@ExceptionHandler 这个注解有个属性,需要定义异常的类型,根据自己需要来,如果你指定了某个异常类,那么就只有这个异常才会被全局捕获到。

具体你想把异常处理成啥样,那你就随便吧,根据你公司实际业务来,或者看你心情也可以。一般的话我们都是会将异常结果处理后根据格式规范返回给前端。

结尾

好了,这个就是全局异常捕获的一些知识了,我个人还是建议大家多去做这种类型的技术的锻炼的,我们要学会对整个系统进行把控,做任何事情都要考虑整个系统的性能和效果,这样才能快速提升自己的能力,从而达到顶级架构师的高度!全局异常捕获一个很小的知识点,但是它代表的是一种能力,代表开发人员对于开发的理解能力和抽象能力,这玩意看不见摸不着,自己多品品。

人世仙家本自殊,何须相见向中途。惊鸿瞥过游龙去,漫恼陈王一事无。我是洛神,我们下期见。

《全局异常捕获》劝劝潘子吧,别再用trycatch来处理异常了相关推荐

  1. spring代码异常捕获到logback logging.config=logback-spring.xml文件中不能输出异常e.printStackTrace...

    在spring中使用logging.config=logback-spring.xml将日志转存到了文件中.但是代码中的捕获的异常无法用 e.printStackTrace 打印到文件中.使用如下方法 ...

  2. 编码技巧——全局异常捕获统一的返回体业务异常

    在开发中,关于异常的捕获曾经是一个头疼的问题:本篇介绍几个方法,如何优雅的捕获处理业务异常: 已检查异常和未检查异常? 先做个介绍,异常Exception分为运行时异常(RuntimeExceptio ...

  3. JEECGJWT异常捕获强化处理

    JEECG&JWT异常捕获强化处理 参考文章: (1)JEECG&JWT异常捕获强化处理 (2) Java: Meaning of catch (final SomeException ...

  4. C++之异常捕获和处理

    C++之异常捕获和处理 参考文章: (1)C++之异常捕获和处理 (2)https://www.cnblogs.com/vachester/p/7599422.html 备忘一下.

  5. Android 全局异常捕获DefaultUncaughtExceptionHandler与Cockroach

    前言 Android中虽然可以通过设置 Thread.setDefaultUncaughtExceptionHandler来捕获全局的所有线程的异常,但主线程抛出异常时仍旧会导致activity闪退, ...

  6. Spring Boot配置全局异常捕获

    1 SpringBoot配置全局的异常捕获 项目的说明 配置thymeleaf作为视图模板 ExceptionController.java模拟测试用 MyAjaxExceptionHandler.j ...

  7. Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获

    Spring boot异常统一处理方法:@ControllerAdvice注解的使用.全局异常捕获.自定义异常捕获 参考文章: (1)Spring boot异常统一处理方法:@ControllerAd ...

  8. atitit.js浏览器环境下的全局异常捕获

    atitit.js浏览器环境下的全局异常捕获 window.onerror = function(errorMessage, scriptURI, lineNumber) { var s= JSON. ...

  9. spring boot: GlobalDefaultExceptionHandler方法内的友好错误提示,全局异常捕获

    spring boot: GlobalDefaultExceptionHandler方法内的友好错误提示,全局异常捕获 当你的某个控制器内的某个方法报错,基本上回显示出java错误代码,非常不友好,这 ...

最新文章

  1. python知识点智能问答_基于知识图谱的智能问答机器人
  2. java接口的修饰符可以为,附架构师必备技术详解
  3. BZOJ 3270: 博物馆
  4. 相机模型与标定(六)--单应性求解
  5. Tushare数据工具介绍
  6. C4D插件X-Particles粒子特效(三)
  7. SketchUp教程:BIG事务所的建筑竞赛分析图表现(附笔刷+处理稿)
  8. springboot+华迪企业合同管理平台 毕业设计-附源码191555
  9. 基于Spring Boot的人力资源管理系统
  10. npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead.
  11. Android Studio 连接手机
  12. 【Linux】Shell脚本:while read line无法读取最后一行???
  13. 分段线性函数三种MIP模型
  14. 化工原理 --- 流体流体 --- 习题课及复习
  15. 苹果mac电脑查看已连接到的wifi密码
  16. Xcode使用OpenCV访问Mac摄像头权限问题
  17. 线控转向,包含设计说明书,carsim模型,MATLAB Simulink模型全套
  18. 火云开发课堂 - 《使用Cocos2d-x 开发3D游戏》系列 第九节:卡通渲染
  19. 关于报错信息为A complete log of this run can be found in:
  20. 【MyBatis-Plus】简介 入门案例

热门文章

  1. 小程序人脸核验功能实现-边读边录(一)
  2. java全文检索word中的内容_搜索引擎时对WORD,EXCEL,PDF,POWERPOINT文件全文检索的总结...
  3. 【安全】靶场实战-通过MS16-032提权
  4. Python requests模块高级用法
  5. 利用html标记制作静态网页,使用HTML制作网页《静态网页制作》.ppt
  6. 批处理命令一日一教学
  7. 基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【八】【完善整个项目】
  8. 炼成的:精妙SQL语句介绍
  9. 带你读懂——频率响应与采样频率之间的关系
  10. MySQL高级-(存储引擎、索引、锁)