@ControllerAdvice全局异常处理器不起作用了?看看我是怎么解决的

本文主要是介绍@ControllerAdvice全局异常处理器不起作用了?看看我是怎么解决的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景:最近项目中使用了@ControllerAdvice+@ExceptionHandler注解组合,实现全局异常处理器,处理代码中手动向上抛出的异常(throws和throw)和自动向上抛出的异常(默认),代码全局异常处理器代码本身写的没问题,但不知道为啥就是不起作用,下面看我怎么解决的吧!

前言:

我们都知道java中异常处理方式有两种

1、就地解决

用try-catch块包裹住容易发生异常的代码片段,这样当该代码片段真正发生异常后,就会立即被catch块捕捉并在catch块中处理,从而使代码继续往下执行,不影响其他代码的执行。

2、向上抛出

如果不想立马就地处理,可以选择将该异常向上抛出,让方法的调用者处理。若方法的调用者也不行处理,同样可以继续向上抛出该异常,以此类推,直到将该异常抛给JVM处理。可是JVM懒啊,一看你们该处理的都不处理是吧,好,我也不处理,我还要把你们方法的调用过程给晒出来,结果就可以在控制台看到方法调用的堆栈信息了。

1、为啥要使用全局异常处理器?

总是用try-catch块包裹代码块也不好,影响性能不说代码看着不是很美观,所以我们选择用第二种——向上抛出的方式。向上抛出没问题,但总要有一个地方处理该异常,在web系统当中还应该将该异常以一个用户可以接受的方式返回给前端,不但在接口对接的时候让前端小姐姐知道是我们后台接口出现了问题,不至于摸不着头脑;而且我们后端开发人员也能根据接口返回的结果快速的知道到底是哪里出现了问题,才能快速解决问题。

2、我的@RestControllerAdvice标注的全局异常处理器

先看下我的全局异常处理器写的没问题是吧:

@RestControllerAdvice //等于@ControllerAdvice+@ResponseBody,和@RestController一个道理
public class OaExpHandler {/*** 处理所有的异常和Throwable类* @param e* @return*/@ExceptionHandler({Exception.class,Throwable.class})public Map<String,Object> testExceptionHandler1(Exception e){System.out.println("进来了");Map<String, Object> map = new HashMap<>();map.put("code",400);map.put("msg","出错啦");return map;}
}  

很简单也没啥问题对吧,但是为啥不行呢?

3、无效的原因

网上有好多是说没有被扫描到,即没有纳入IOC容器中,这确实是一个原因,但我怎么会犯这个错误呢?

其实还有一个原因,@ControllerAdvice全局异常处理器是处理controller中向上抛出后没有被处理的异常,若异常在到达该异常处理器前就已经被处理了,自然就不会到达@ExceptionHandler标注的方法处理。我的就是这个原因...

我看了下controller中没有try-catch块,但是我有两个切面,对所有的controller方法进行了环绕通知——找到原因了啊。

一起看看罪魁祸首:

@Around("controllerPointcutExpress() || actControllerPointcutExpress()")public Object execTimeAround(ProceedingJoinPoint joinPoint) throws Throwable {Object result = null;long start = System.currentTimeMillis();/*try {result = joinPoint.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}*/result = joinPoint.proceed();//获取目标方法的全类名MethodSignature signature = (MethodSignature)joinPoint.getSignature();Method targetMethod = signature.getMethod();System.out.println("目标方法:"+targetMethod +"执行总时长为------- {"+(System.currentTimeMillis() - start)+"}毫秒");return result;}

被注释的代码就是那段有罪的代码,可以看到我用try-catch块对proceed()方法进行了包裹,所以一旦目标方法出现了异常,这里的catch块就会非常勤快的捕捉到异常并处理掉,自然没有向上抛出去,也就无法到达@ControllerAdvice标注的全局异常处理器中。看到这里不禁会问,嗯?难道Aspect切面的执行顺序在@ControllerAdvice之前?但是事实上就是这个样子的。

4、根本原因

一张图足以说明一切:

springMVC请求与响应中各组件的执行顺序

看完本篇文章只要能学到两点就可以了

1、理解java异常处理的机制。

2、知道filter、interceptor、controllerAdvice、Aspect、controller在springMVC中的执行顺序。

 

好了,今天就到这里吧,希望看完本篇文章能解决你的问题,若能学点东西就更好了。

另外,祝你每天开心、升职加薪、生活幸福!

 

 

 

 

这篇关于@ControllerAdvice全局异常处理器不起作用了?看看我是怎么解决的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/502295

相关文章

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

linux报错INFO:task xxxxxx:634 blocked for more than 120 seconds.三种解决方式

《linux报错INFO:taskxxxxxx:634blockedformorethan120seconds.三种解决方式》文章描述了一个Linux最小系统运行时出现的“hung_ta... 目录1.问题描述2.解决办法2.1 缩小文件系统缓存大小2.2 修改系统IO调度策略2.3 取消120秒时间限制3

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

怎么关闭Ubuntu无人值守升级? Ubuntu禁止自动更新的技巧

《怎么关闭Ubuntu无人值守升级?Ubuntu禁止自动更新的技巧》UbuntuLinux系统禁止自动更新的时候,提示“无人值守升级在关机期间,请不要关闭计算机进程”,该怎么解决这个问题?详细请看... 本教程教你如何处理无人值守的升级,即 Ubuntu linux 的自动系统更新。来源:https://

Ubuntu系统怎么安装Warp? 新一代AI 终端神器安装使用方法

《Ubuntu系统怎么安装Warp?新一代AI终端神器安装使用方法》Warp是一款使用Rust开发的现代化AI终端工具,该怎么再Ubuntu系统中安装使用呢?下面我们就来看看详细教程... Warp Terminal 是一款使用 Rust 开发的现代化「AI 终端」工具。最初它只支持 MACOS,但在 20

Mysql DATETIME 毫秒坑的解决

《MysqlDATETIME毫秒坑的解决》本文主要介绍了MysqlDATETIME毫秒坑的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 今天写代码突发一个诡异的 bug,代码逻辑大概如下。1. 新增退款单记录boolean save = s

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修