《全局异常捕获》劝劝潘子吧,别再用trycatch来处理异常了
人世仙家本自殊,何须相见向中途。惊鸿瞥过游龙去,漫恼陈王一事无。
嗨,大家好,我是洛神,性别男。一个来自快乐星球的程序员。
欢迎大家专注我的公众号【程序员洛神】,不仅分享技术,还会分享生活趣事、体育。
前言
前几天闲来无事看之前的项目,发现项目中对异常问题的处理非常不优雅,有些接口中为了处理异常使用的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来处理异常了相关推荐
- spring代码异常捕获到logback logging.config=logback-spring.xml文件中不能输出异常e.printStackTrace...
在spring中使用logging.config=logback-spring.xml将日志转存到了文件中.但是代码中的捕获的异常无法用 e.printStackTrace 打印到文件中.使用如下方法 ...
- 编码技巧——全局异常捕获统一的返回体业务异常
在开发中,关于异常的捕获曾经是一个头疼的问题:本篇介绍几个方法,如何优雅的捕获处理业务异常: 已检查异常和未检查异常? 先做个介绍,异常Exception分为运行时异常(RuntimeExceptio ...
- JEECGJWT异常捕获强化处理
JEECG&JWT异常捕获强化处理 参考文章: (1)JEECG&JWT异常捕获强化处理 (2) Java: Meaning of catch (final SomeException ...
- C++之异常捕获和处理
C++之异常捕获和处理 参考文章: (1)C++之异常捕获和处理 (2)https://www.cnblogs.com/vachester/p/7599422.html 备忘一下.
- Android 全局异常捕获DefaultUncaughtExceptionHandler与Cockroach
前言 Android中虽然可以通过设置 Thread.setDefaultUncaughtExceptionHandler来捕获全局的所有线程的异常,但主线程抛出异常时仍旧会导致activity闪退, ...
- Spring Boot配置全局异常捕获
1 SpringBoot配置全局的异常捕获 项目的说明 配置thymeleaf作为视图模板 ExceptionController.java模拟测试用 MyAjaxExceptionHandler.j ...
- Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获
Spring boot异常统一处理方法:@ControllerAdvice注解的使用.全局异常捕获.自定义异常捕获 参考文章: (1)Spring boot异常统一处理方法:@ControllerAd ...
- atitit.js浏览器环境下的全局异常捕获
atitit.js浏览器环境下的全局异常捕获 window.onerror = function(errorMessage, scriptURI, lineNumber) { var s= JSON. ...
- spring boot: GlobalDefaultExceptionHandler方法内的友好错误提示,全局异常捕获
spring boot: GlobalDefaultExceptionHandler方法内的友好错误提示,全局异常捕获 当你的某个控制器内的某个方法报错,基本上回显示出java错误代码,非常不友好,这 ...
最新文章
- python知识点智能问答_基于知识图谱的智能问答机器人
- java接口的修饰符可以为,附架构师必备技术详解
- BZOJ 3270: 博物馆
- 相机模型与标定(六)--单应性求解
- Tushare数据工具介绍
- C4D插件X-Particles粒子特效(三)
- SketchUp教程:BIG事务所的建筑竞赛分析图表现(附笔刷+处理稿)
- springboot+华迪企业合同管理平台 毕业设计-附源码191555
- 基于Spring Boot的人力资源管理系统
- npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead.
- Android Studio 连接手机
- 【Linux】Shell脚本:while read line无法读取最后一行???
- 分段线性函数三种MIP模型
- 化工原理 --- 流体流体 --- 习题课及复习
- 苹果mac电脑查看已连接到的wifi密码
- Xcode使用OpenCV访问Mac摄像头权限问题
- 线控转向,包含设计说明书,carsim模型,MATLAB Simulink模型全套
- 火云开发课堂 - 《使用Cocos2d-x 开发3D游戏》系列 第九节:卡通渲染
- 关于报错信息为A complete log of this run can be found in:
- 【MyBatis-Plus】简介 入门案例
热门文章
- 小程序人脸核验功能实现-边读边录(一)
- java全文检索word中的内容_搜索引擎时对WORD,EXCEL,PDF,POWERPOINT文件全文检索的总结...
- 【安全】靶场实战-通过MS16-032提权
- Python requests模块高级用法
- 利用html标记制作静态网页,使用HTML制作网页《静态网页制作》.ppt
- 批处理命令一日一教学
- 基于springboot+bootstrap+mysql+redis搭建一套完整的权限架构【八】【完善整个项目】
- 炼成的:精妙SQL语句介绍
- 带你读懂——频率响应与采样频率之间的关系
- MySQL高级-(存储引擎、索引、锁)