美文网首页
统一异常处理导致ResponseBodyAdvice失效

统一异常处理导致ResponseBodyAdvice失效

作者: 日楚东山 | 来源:发表于2022-07-25 19:07 被阅读0次

背景

微服务架构下准备将一些基础功能抽出到公共Jar包中,包括统一异常处理、JwtToken校验、统一请求响应处理等,抽完以后发现,当出现异常时,走了统一异常捕获的逻辑,但是项目中的所有自定义的ResponseBodyAdvice都没有执行,决定一步步DEBUG定位下原因,项目是Springboot 2.3.7.RELEASE版本。

定位过程

首先测试正常的接口,发现ResponseBodyAdvice都是生效的,而且按照设置的顺序执行了,说明这些ResponseBodyAdvice都注册到容器了。

接着猜测是不是ResponseBodyAdvice都执行过只是没有执行beforeBodyWrite方法,在执行supports方法的时候就已经返回,于是在supports方法里面打上断点,看抛异常时是否会走到supports方法,最后发现都没有走supports方法,猜测可能是因为什么规则,把ResponseBodyAdvice都过滤了。

继续DEBUG,看正常流程下ResponseBodyAdvice是如何生效的,因为之前在supports方法都打了断点,直接请求接口,看supports方法之前的调用调用堆栈,如图

stack.jpg

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

AbstractMessageConverterMethodProcessor.jpg

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

RequestResponseBodyAdviceChain.jpg

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

getMatchAdvice.jpg

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

beanTypePredicate.jpg

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

test.jpg

到这就能大概知道原因了,就是包名不匹配,ResponseBodyAdvice只能处理指定包名下的返回值处理。其他两个属性可以实现指定注解或者Class类实现ResponseBodyAdvice的功能:

  • annotations属性,如果返回的方法不在basePackages包内,直接在方法上指定这个注解
  • assignableTypes属性,如果不在basePackages包内,也没有annotations注解,指定Class类也可以

原因

统一异常处理类所在的包名不在@RestControllerAdvice注解的basePackages属性指定的包名下,所以自定义的ResponseBodyAdvice是处理不了统一异常处理返回的数据的

解决方法

  • 修改包名,basePackages的包名包含统一异常处理的类
  • 增加自定义注解,修饰在异常处理的方法上,并把这个注解写在@RestControllerAdvice注解的annotations属性上
  • 将异常处理的类Class对象写在@RestControllerAdvice注解的assignableTypes属性上

总结

框架异常多看源码,多调试,有很大收获。

相关文章

  • 统一异常处理导致ResponseBodyAdvice失效

    背景 微服务架构下准备将一些基础功能抽出到公共Jar包中,包括统一异常处理、JwtToken校验、统一请求响应处理...

  • Springboot使用了ResponseBodyAdvice处

    为了统一接口响应的报文,现实了ResponseBodyAdvice接口,通过这个接口的实现类来统一处理报文 然而在...

  • spring/springmvc 全局异常处理

    1.在项目中为什么要统一异常处理 当异常返回到前端页面的时候可以统一处理,避免前端无法处理异常 不做统一异常处理,...

  • 统一异常处理

    一、什么是统一异常处理 1、制造异常 2、什么是统一异常处理我们想让异常结果也显示为统一的返回结果对象,并且统一处...

  • springboot全局异常处理

    一、单个controller范围的异常处理/** 统一异常处理 @return*/@RequestMapping(...

  • springboot之统一异常处理

    spring统一异常处理 使用spring的统一异常处理,我们就不再需要在业务代码中就行显式的捕获异常处理,在da...

  • 统一异常处理

    1.定义返回结果对象 2.定义返回结果工具类, 3.枚举消息状态 .4.自定义异常类 5.统一异常拦截 6.业务中...

  • 统一异常处理

    首先,利用枚举,来定义异常类型。定义枚举ResultEnum: 自定义异常,新建CustomException类:...

  • 统一异常处理

    简要描述: 在web层controller业务代码中,一般不要处理任何异常,将异常完全跑出,由ExceptionH...

  • 统一异常处理

    Overview 利用Spring AOP思想,对项目中的异常进行统一处理。 实现思路 通过@Controller...

网友评论

      本文标题:统一异常处理导致ResponseBodyAdvice失效

      本文链接:https://www.haomeiwen.com/subject/cqzoirtx.html