SpringBoot:如何优雅地处理全局异常?
之前用springboot的时候,只知道捕获异常使用try{}catch,一个接口一个try{}catch,这也是大多数开发人员异常处理的常用方式,虽然屡试不爽,但会造成一个问题,就是一个controller下面,满屏幕的try{}catch,看着一点都不优雅,一点都不符合小明的气质,憋了这么久,小明今天终于决定对所有异常实施统一处理的方案。
开发准备
jdk8、正常的springboot项目
代码编写
通用异常处理
其实spring系列的项目全局异常处理方式早已存在,只不过我们一直忙于搬砖,很少停下脚步去审视这个日夜与我们相伴的朋友。为了贴合主题,本次主要针对springboot全局异常处理进行举例说明。
springboot中有一个@controlleradvice
的注解,使用该注解即表示开启全局异常捕获,接下来我们只需在自定义的方法上使用@exceptionhandler
注解,并定义捕获异常的类型,对这种类型的异常进行统一的处理。
举个例子:
假如我们需要针对nullexception(空指针异常,是java程序员最痛恨的异常,没有之一)进行全局处理(如下所示)。
@restcontrolleradvice public class globalexceptionhandler { /** * 处理空指针的异常 * @param req * @param e * @return */ @exceptionhandler(value =nullpointerexception.class) public baseresponsefacade exceptionhandler(httpservletrequest req, nullpointerexception e){ log.error("发生空指针异常!原因是:",e); return responseutil.error(responsecode.error); } }
讷,就这么简单。其他可能发生的异常,都可以以这种方式处理快速处理。此处大家应该表现的十分兴奋,但请不要高兴太早,因为接下来,有更令激动人心的事情。
自定义异常处理
自定义一个异常
import lombok.allargsconstructor; import lombok.data; import lombok.experimental.accessors; /** * @description 自定义异常 * @date 2019-08-05 15:49 * @created by 程序员小明 */ @data @allargsconstructor @accessors(chain = true) public class bizexception extends runtimeexception { /** * 错误码 */ protected integer errorcode; /** * 错误信息 */ protected string errormsg; }
显而易见,这个异常继承了runtimeexception
,属于运行时异常。细心的朋友已经发现,我使用了lombok插件,非常契合今天的主题,给大家简单介绍一下:
lombok是一个可以帮助我们简化java代码编写的工具类,尤其是简化javabean的编写,即通过采用注解的方式,消除代码中的构造方法,getter/setter等代码,使我们写的类更加简洁(如果使用的ide是idea,需要安装插件哈)。
定义过之后,我们就可以和之前处理nullexception方式一样处理我们自定义的异常。包括处理其他异常,都是这种方式。直接贴代码。
@slf4j @restcontrolleradvice public class globalexceptionhandler { /** * 处理自定义的业务异常 * @param req * @param e * @return */ @exceptionhandler(value = bizexception.class) public baseresponsefacade bizexceptionhandler(httpservletrequest req, bizexception e){ log.error("发生业务异常!原因是:{}",e.geterrormsg()); return responseutil.error(e.geterrorcode(),e.geterrormsg()); } /** * 处理空指针的异常 * @param req * @param e * @return */ @exceptionhandler(value =nullpointerexception.class) public baseresponsefacade exceptionhandler(httpservletrequest req, nullpointerexception e){ log.error("发生空指针异常!原因是:",e); return responseutil.error(responsecode.error); } /** * 处理其他异常 * @param req * @param e * @return */ @exceptionhandler(value =exception.class) public baseresponsefacade exceptionhandler(httpservletrequest req, exception e){ log.error("未知异常!原因是:",e); return responseutil.error(responsecode.internal_server_error); } }
整个全局异常处理方式核心就是以上介绍这些。下面用一个demo给大家举个例子
@getmapping("/test") public baseresponsefacade test(){ if(true){ throw new bizexception(1,"error"); } return responseutil.success(); }
地址栏请求,进入这个方法后,会抛出异常,此时全局异常生效,就会返回异常处理过后的信息
{"errorcode":1,"errormsg":"error","data":null}
到此整个流程都然跑通了。当然,好多地方都可以根据我们自身实际业务情况以此为基础进一步丰富,比如返回数据可以改成跳转某一个具体的页面。这样的出场方式是不是都很优雅?大家有什么问题,期待各位留言。
上一篇: 缓存世界中的三大问题及解决方案
下一篇: oracle数据库与其他数据库区别