美文网首页
统一异常处理导致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失效

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