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的深度最小。

相关推荐
飞翔的佩奇6 分钟前
Java项目:基于SSM框架实现的忘忧小区物业管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告】
java·数据库·mysql·vue·毕业设计·ssm框架·小区物业管理系统
程序员爱钓鱼13 分钟前
Go语言泛型-泛型约束与实践
前端·后端·go
寻月隐君13 分钟前
保姆级教程:Zsh + Oh My Zsh 终极配置,让你的 Ubuntu 终端效率倍增
linux·后端·命令行
程序员爱钓鱼16 分钟前
Go语言泛型-泛型对代码结构的优化
后端·google·go
这里有鱼汤21 分钟前
“对象”?对象你个头!——Python世界观彻底崩塌的一天
后端·python
RainbowSea23 分钟前
跨域问题(Allow CORS)解决(3 种方法)
java·spring boot·后端
掘金-我是哪吒25 分钟前
分布式微服务系统架构第155集:JavaPlus技术文档平台日更-Java线程池实现原理
java·分布式·微服务·云原生·架构
RainbowSea28 分钟前
问题 1:MyBatis-plus-3.5.9 的分页功能修复
java·spring boot·mybatis
前端 贾公子31 分钟前
monorepo + Turborepo --- 开发应用程序
java·前端·javascript
不学会Ⅳ1 小时前
Mac M芯片搭建jdk源码环境(jdk24)
java·开发语言·macos