当前位置:网站首页>统一异常处理导致ResponseBodyAdvice失效
统一异常处理导致ResponseBodyAdvice失效
2022-07-30 08:16:00 【AE86Jag】
背景
微服务架构下准备将一些基础功能抽出到公共Jar包中,包括统一异常处理、JwtToken校验、统一请求响应处理等,抽完以后发现,当出现异常时,走了统一异常捕获的逻辑,但是项目中的所有自定义的ResponseBodyAdvice都没有执行,决定一步步DEBUG定位下原因,项目是Springboot 2.3.7.RELEASE版本。
定位过程
首先测试正常的接口,发现ResponseBodyAdvice都是生效的,而且按照设置的顺序执行了,说明这些ResponseBodyAdvice都注册到容器了。
接着猜测是不是ResponseBodyAdvice都执行过只是没有执行beforeBodyWrite方法,在执行supports方法的时候就已经返回,于是在supports方法里面打上断点,看抛异常时是否会走到supports方法,最后发现都没有走supports方法,猜测可能是因为什么规则,把ResponseBodyAdvice都过滤了。
继续DEBUG,看正常流程下ResponseBodyAdvice是如何生效的,因为之前在supports方法都打了断点,直接请求接口,看supports方法之前的调用调用堆栈,如图

主要是前面几个类,栈顶是我自定义的ResponseBodyAdvice,断点打在supports方法上,下面是RequestResponseBodyAdviceChain的processBody方法140行,然后是RequestResponseBodyAdviceChain的beforeBodyWrite方法116行,AbstractMessageConverterMethodProcessor类的writeWithMessageConverters268行,分别在这几个方法上打断点:

下面会走RequestResponseBodyAdviceChain的beforeBodyWrite方法,继续进去看下

for循环里面就是实际去调用每个advice去处理返回结果,要过滤就只能在getMatchingAdvice方法里面了,继续DEBUG

getAdvice()就是获取系统中所有的Advice,因为自定义的ResponseBodyAdvice都是有@ControllerAdvice注解修饰的,所以都是ControllerAdviceBean类型,走的157行的逻辑。parameter参数就是最终返回数据的方法参数,我这里就是统一异常处理的方法。继续进入

可以看到这个方法调用了beanTypePredicate的test方法,beanTypePredicate里面有三个属性,其中有一个是basePackages,在自定义的ResponseBodyAdvice中@RestControllerAdvice指定了包名,其他两个assignableTypes、annotations也是该注解的属性。继续看test方法的内容

到这就能大概知道原因了,就是包名不匹配,ResponseBodyAdvice只能处理指定包名下的返回值处理。其他两个属性可以实现指定注解或者Class类实现ResponseBodyAdvice的功能:
- annotations属性,如果返回的方法不在basePackages包内,直接在方法上指定这个注解
- assignableTypes属性,如果不在basePackages包内,也没有annotations注解,指定Class类也可以
原因
统一异常处理类所在的包名不在@RestControllerAdvice注解的basePackages属性指定的包名下,所以自定义的ResponseBodyAdvice是处理不了统一异常处理返回的数据的
解决方法
- 修改包名,basePackages的包名包含统一异常处理的类
- 增加自定义注解,修饰在异常处理的方法上,并把这个注解写在@RestControllerAdvice注解的annotations属性上
- 将异常处理的类Class对象写在@RestControllerAdvice注解的assignableTypes属性上
总结
框架异常多看源码,多调试,有很大收获。
边栏推荐
- 剖析SGI STL空间配置器(_S_refill内存块填充函数)
- OA Project Pending Meeting & History Meeting & All Meetings
- hcip 第14天学习笔记
- 20个电路能懂5个以上,足以证明你在电子行业混过!
- It is said that FPGA is high-end, what can it do?
- 一文带你玩转offer-01
- Alibaba Cloud Cloud Server Firewall Settings
- jdbc ResultSetMetaData获取tableName问题
- How to Assemble a Registry
- ACL 2022 | Introduce angular margin to construct comparative learning objectives and enhance text semantic discrimination ability
猜你喜欢

SwiftUI SQLite 教程之 构建App本地数据库实现创建、读取、更新和删除(教程含完成项目源码)

sql注入数据库原理详解

基于SSM实现高校后勤报修系统

One article to understand twenty kinds of switching power supply topologies

Leetcode - 990: equations of satisfiability

剖析SGI STL空间配置器(一 、辅助接口函数)

英语语法-名词性从句

OA Project Pending Meeting & History Meeting & All Meetings

一文读懂二十种开关电源拓扑结构

typescript5 - compile and install ts code
随机推荐
Field interpretation under "Surgical variables (RX SUMM-SURG OTH REG/DIS)" in SEER database
The difference between typescript3-ts and js
ACL 2022 | Introduce angular margin to construct comparative learning objectives and enhance text semantic discrimination ability
如何避免CMDB沦为数据孤岛?
How to Assemble a Registry
电脑文档误删除怎么恢复,恢复误删除电脑文档的方法
Windows 下安装 MySQL
hicp第六天
电源完整性的去耦和层间耦合电容
【无标题】
typescript4 - installs a toolkit for compiling ts
R安装包出现error in rawtochar(block[seq_len(ns)]) :
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(另附课设大作业参考)
Alibaba Cloud Cloud Server Firewall Settings
ACL 2022 | 引入角度margin构建对比学习目标,增强文本语义判别能力
集合相关Collection
剖析SGI STL空间配置器(一 、辅助接口函数)
How to run dist file on local computer
test2
iperf3 参数选项详细说明