Spring Boot 统一功能处理(三)

本篇主要介绍Spring Boot的统一异常处理。

目录

一、统一异常处理的使用

二、测试统一异常处理效果

三、浅析原理

@ControllerAdvice简析

统一处理异常简析


一、统一异常处理的使用

在前面介绍统一数据返回时,我们在程序发生异常时会把整个报错信息都封装在data里返回给前端,这显然是不太合适的,毕竟让懂后端的前端看到这些具体的报错信息还挺羞耻的,因此我们来看一下如何对异常进行统一处理。

首先我们需要创建统一处理异常的类,并加上@ControllerAdvice注解:

接下来我们需要自己定义一个处理异常的具体方法handler,其参数为需要处理的异常,并在方法上加上@ExceptionHandler注解:

如果需要处理多个异常,则可以重载handler方法:

定义完这些方法之后,当我们的程序发生异常时则会自动执行这里对应的handler方法来进行统一的异常处理,并将handler的返回结果写到响应数据里,但由于Spring默认是返回Html,因此我们还需要在方法或者类上加上@RespondyBody注解来调整返回数据类型。

二、测试统一异常处理效果

接下来我们来测试一下统一异常处理的效果:

在Controller里,定义两个test方法,并分别制造一个异常,一个为空指针异常,一个为算术异常:

然后我们再修改一下前面定义的handler,让其更加规范一点

接下来我们通过PostMan来测试一下前面定义的这两个方法:

访问test05

访问test06

通过测试结果可以发现,当由于空指针异常在我们定义的统一处理类中进行对应的实现,因此调用了参数为空指针异常的handler方法,而算术异常则没有对应实现,所以调用了以Exception为参数的handler方法来处理,因此我们可以得出结论,当发生异常时会优先去寻找与异常类型一致的handler方法来进行处理,如果没有类型一致的则会去找参数为当前异常的类型的上级(父类)的handler方法来处理,其内部具体逻辑将在下文介绍。

三、浅析原理

@ControllerAdvice简析

前面在介绍初始化DispatchServerlet时,提到过在初始化最后会初始化九大组件,这九大组件中有一个HandlerAdapters,初始化这个组件时会去获取所有实现了HandlerAdapt的Bean,在这些Bean中有一个叫做RequestMappingHandlerAdapt,这个Bean会获取所有加了@ControllerAdvice注解的Bean,并进行处理。

处理完后,一旦发生了这些加了@ControllerAdvice标注的Bean对应的事件,就会调用其对应的Advice方法,例如在进行统一功能处理时,如果有数据返回了,系统就会在这个里面找对应的Bean,并调用这个bean中处理返回数据的方法。

统一处理异常简析

对于统一异常的处理,还是得追溯到九大组件,在这九大组件里有一个HandlerExceptionResolvers,初始化这个组件会去获取所有实现HandlerExceptionResolvers接口的Bean,在这些Bean中,有一个叫ExceptionHandlerExceptionResolvers的Bean,这个也会去获取所有@ControllerAdvice标注的Bean

并且它会创建一个ExceptionHandlerMethondResolver。

当项目里有异常发生时 ,会通过DispathcServerlet来解析异常,而DispatchServerlet则会通过ExceptionHandlerExceptionReslover来解析异常,最后ExceptionHandlerExceptionReslover再通过这个ExceptionHandlerMethondResolve来解析异常。ExceptionHandlerMethondResolve会将异常解析到前面对应的加了@ExceptionHandler的handler方法,具体为如下这串代码。

在这个代码里,会先创建一个List metches,

然后去获取当前异常能够匹配到的所有异常类型(包括当前异常的类型及其所有父类异常的类型),

并将这些类型添加到matches里。如果在matches添加了不止一个,也就是matches.size() > 1 ,就会对matches按类型的深度进行排序(例如当前异常类型为NullpointException,那么NullpointException的深度就为0,其父类RuntimeException的深度则为1,然后以此类推,每往上一级,深度就加一),

排完序后,则会将参数为matches中第一个类型(也就是深度最小的异常类型)这种类型的加了@Exception批注的handler方法返回。最后再由其它类来执行这个方法。

所以在前面我们在前面测试test05时访问的是参数为NullpointException的handler方法,因为在访问test05时会发生空指针异常,而发生空指针异常时NullpointException的深度最小。

相关推荐
酷炫码神13 分钟前
MosMos 创意效果与能力边界展示
java
Wang's Blog19 分钟前
Java 接入Redis: 使用Jedis操作Redis
java·服务器·redis
苏三说技术21 分钟前
Spring AI、LangChain4j、AgentScope、Embabel,哪个AI框架更好?
后端
事圆则缓22 分钟前
Java 8 Lambda、Stream、Optional 与 Android 边界:从回调语法到运行时兼容
android·java
shehuiyuelaiyuehao31 分钟前
算法50,分治归并,数组中的逆序对
java·算法
烽学长32 分钟前
(附源码)基于Springboot+vue的图书阅读分享系统的设计与实现
java·spring boot·后端
isfox36 分钟前
Python 单例模式:一个类只能有一个实例,到底怎么实现?
后端
Ivanqhz38 分钟前
数据搬运是性能关键
java·服务器·网络·人工智能·深度学习
青山木1 小时前
RocketMQ 入门到原理(三):消息存储原理
java·后端·中间件·架构·rocketmq