当前位置: 首页 > news >正文

springmvc 全局异常处理器配置的三种方式深入底层源码分析原理

文章目录

  • springmvc 全局异常处理器配置的三种方式&深入底层源码分析原理
    • 配置全局异常处理器的三种方式
      • 实现接口HandlerExceptionResolver并配置到WebMvcConfigurer
      • 注解式配置@ExceptionHandler
      • controller里方法上定义@ExceptionHandler
    • 深入源码分析
      • 进入DispatcherServlet
      • 执行handler方法并catch异常

springmvc 全局异常处理器配置的三种方式&深入底层源码分析原理

配置全局异常处理器的三种方式

实现接口HandlerExceptionResolver并配置到WebMvcConfigurer

定义一个类实现这个接口


/*** Interface to be implemented by objects that can resolve exceptions thrown during* handler mapping or execution, in the typical case to error views. Implementors are* typically registered as beans in the application context.** <p>Error views are analogous to JSP error pages but can be used with any kind of* exception including any checked exception, with potentially fine-grained mappings for* specific handlers.** @author Juergen Hoeller* @since 22.11.2003*/
public interface HandlerExceptionResolver {/*** Try to resolve the given exception that got thrown during handler execution,* returning a {@link ModelAndView} that represents a specific error page if appropriate.* <p>The returned {@code ModelAndView} may be {@linkplain ModelAndView#isEmpty() empty}* to indicate that the exception has been resolved successfully but that no view* should be rendered, for instance by setting a status code.* @param request current HTTP request* @param response current HTTP response* @param handler the executed handler, or {@code null} if none chosen at the* time of the exception (for example, if multipart resolution failed)* @param ex the exception that got thrown during handler execution* @return a corresponding {@code ModelAndView} to forward to,* or {@code null} for default processing in the resolution chain*/@NullableModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);}

定义一个配置类实现接口 WebMvcConfigurer 并重写方法configureHandlerExceptionResolvers将你定义的这个resolver加入到resolvers这个List即可

注解式配置@ExceptionHandler

要让spring扫描到这个类,一种方式是直接把这个类放到springboot能扫描的目录下(启动类当前目录或者子目录,或者在启动类手动配置的扫描组件目录),另一种方式是放在工具类里,定义到spring.factories里让spring扫描到,注意设置个@Order(0)让这个优先于springmvc注解错误处理器之前注入到容器,否则会无效,因为那个处理器只加载一次,后续不会再扫容器里的实例了。

/*** @author humorchen* date: 2024/6/11* description: 认证全局异常配置**/@Slf4j
@RestControllerAdvice
@Order(0)
public class AuthExceptionResolver {public static final int TOKEN_ERROR_CODE = HttpStatus.HTTP_UNAUTHORIZED;public static final String ERROR_MSG = "未登录或登录已失效!";/*** TOKEN相关异常** @param e* @return*/@ExceptionHandler({SaTokenException.class, JWTVerificationException.class})public Result<String> resolveAuthTokenException(Exception e) {log.info("handleSaTokenException {}: {}", e.getClass().getName(), e.getMessage());return Result.fail(TOKEN_ERROR_CODE, ERROR_MSG);}}

看到上面代码,你会有一个疑问,要是定义了多个,它怎么确定该用哪个呢,源码中使用ExceptionDepthComparator排序,排序规则是按照继承顺序来(继承关系越靠近数值越小,当前类最小为0,顶级父类Throwable为int最大值),排序之后选取继承关系最靠近的那个,并且ExceptionHandlerMethodResolver的exceptionLookupCache中,key为当前抛出的异常,value为解析出来的匹配method.
org.springframework.core.ExceptionDepthComparator
在这里插入图片描述

controller里方法上定义@ExceptionHandler

@RestController
public class ExceptionController {@ExceptionHandler(Exception.class)public ResponseEntity<String> handleException(Exception ex) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred: " + ex.getMessage());}@RequestMapping("/test")public String test() throws Exception {throw new Exception("Test exception!");}
}

深入源码分析

进入DispatcherServlet

在这里插入图片描述

执行handler方法并catch异常

在这里插入图片描述
调用processDispatchResult处理分发处理结果
在这里插入图片描述

发现有异常则调用processHandlerException 处理handler异常
在这里插入图片描述

如果有handlerExceptionResovlers就循环调用,直到有一个resolver返回了非空值就跳出循环
在这里插入图片描述
默认resolver,就是把这个异常放到了request.attribute里头去了

在这里插入图片描述

在这里插入图片描述

HandlerExceptionResolverComposite,是handler异常处理器的复合类,把这些resolver放到它内部一个集合
在这里插入图片描述
在这里插入图片描述
点开这个类源码看下,其实就是在我们在webmvcconfigurer里配置这个方法的时候,把配置的所有resolver设置进这个类里的this.resolvers 集合去了,进调试可以看到有两个resolver,一个是我自定义并配置上的ExceptionResolver,另一个是个Http请求异常处理器(seata的HttpHandlerExceptionResolver)
在这里插入图片描述

在这里插入图片描述
分布式事务用来清理ID的,不用管

在这里插入图片描述
第三个也是我注入的那个错误处理器
如果经过这些处理器,有一个返回了非空的结果,这个异常 处理就会被结束

在这里插入图片描述
执行完所有的resolver,有一个返回了ModelAndView的话就返回这个ModelAndView,否则继续抛出异常往上层传递。然后触发请求handler的triggerAfterCompletion,也就是执行你所有跟这个handler绑定的HandlerInterceptor的afterCompletion

在这里插入图片描述

前面看的都是HandlerExceptionResolver的实现,还有那个注解式的实现,我们也一起看下这个ExceptionHandlerExceptionResolver 类的源码,就是用来处理 @ExceptionHandler的

/*** An {@link AbstractHandlerMethodExceptionResolver} that resolves exceptions* through {@code @ExceptionHandler} methods.** <p>Support for custom argument and return value types can be added via* {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.* Or alternatively to re-configure all argument and return value types use* {@link #setArgumentResolvers} and {@link #setReturnValueHandlers(List)}.** @author Rossen Stoyanchev* @author Juergen Hoeller* @since 3.1*/
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolverimplements ApplicationContextAware, InitializingBean {@Nullableprivate List<HandlerMethodArgumentResolver> customArgumentResolvers;@Nullableprivate HandlerMethodArgumentResolverComposite argumentResolvers;@Nullableprivate List<HandlerMethodReturnValueHandler> customReturnValueHandlers;@Nullableprivate HandlerMethodReturnValueHandlerComposite returnValueHandlers;private List<HttpMessageConverter<?>> messageConverters;private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();private final List<Object> responseBodyAdvice = new ArrayList<>();@Nullableprivate ApplicationContext applicationContext;private final Map<Class<?>, ExceptionHandlerMethodResolver> exceptionHandlerCache =new ConcurrentHashMap<>(64);private final Map<ControllerAdviceBean, ExceptionHandlerMethodResolver> exceptionHandlerAdviceCache =new LinkedHashMap<>();

在这个bean执行到afterPropertiesSet这个时间点的时候进行了 @ExceptionHandler实现的扫描initExceptionHandlerAdviceCache(),如果你的 @ExceptionHandler配置bean在这个时间点之后注入进IOC容器的话,那么恭喜你,你的配置不会生效,因此前面我说要让自己的这个配置优先级变高,才能生效。
在这里插入图片描述
ControllerAdviceBean.findAnnotatedBeans(getApplicationContext())
把所有的标注了@ControllerAdvice注解的bean全部找出来并根据order排序返回了

在这里插入图片描述

在这里插入图片描述

看到这你会疑问还有个@RestControllerAdvice,来看源码,@RestControllerAdvice上标注了@ControllerAdvice
在这里插入图片描述
前面已经看了加载过程,现在看执行处理异常的代码,其实就是拿着加载好的处理器,去调用处理,然后参数呢又是可选的,随便你定义,那个其实是反射拿到你方法定义的参数,然后跟现有能给你的一些参数比对类型,然后组成一个参数数组,传入执行对象、参数反射执行方法,然后就拿到了异常处理结果

在这里插入图片描述
组装生成调用参数数组的方法就在这org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
在这里插入图片描述
也就是把异常对象和当前的handlerMethod给你了,你自己可以写到参数里它会注入给你的
在这里插入图片描述

在这里插入图片描述

ExceptionHandler原理另一个作者也写的不错:
从源码角度去深入分析关于Spring的异常处理ExceptionHandler的实现原理

相关文章:

springmvc 全局异常处理器配置的三种方式深入底层源码分析原理

文章目录 springmvc 全局异常处理器配置的三种方式&深入底层源码分析原理配置全局异常处理器的三种方式实现接口HandlerExceptionResolver并配置到WebMvcConfigurer注解式配置ExceptionHandlercontroller里方法上定义ExceptionHandler 深入源码分析进入DispatcherServlet执…...

MySQL 8.0 安装、配置、启动、登录、连接、卸载教程

目录 前言1. 安装 MySQL 8.01.1 下载 MySQL 8.01.2 安装 MySQL 8.0 2. 配置 MySQL 8.02.1打开环境变量2.2新建变量 MYSQL_HOME2.3编辑 Path 变量 3. 启动MySQL 8.03.1验证安装与配置是否成功3.2初始化并注册MYSQL3.3 启动MYSQL服务 4.登录MySQL4.1修改账户默认密码4.2登录MYSQL…...

Pythone 程序打包成 exe

1.安装pyinstaller # 安装 pip install pyinstaller # 查看版本 pyinstaller -v2.更新pyinstaller 版本 # 更新 pip install --upgrade pyinstaller # 查看版本 pyinstaller -v3.切换到 py文件所在目录 #切换到.py所在的目录 E: cd cd E:\x-svn_x-local\04PythoneProjects\A…...

“卫星-无人机-地面”遥感数据快速使用及地物含量计算

随着我国高分系列、欧比特系列、自然资源卫星系列等卫星数据的获取&#xff0c;以及美国Headwall、芬兰SPECIM、挪威HySpex、我国双利合谱、智科远达、中科谱光等无人机数据的兴起&#xff0c;遥感数据越来越易得。这些多源数据&#xff0c;在与典型地面点结合后&#xff0c;将…...

设计模式学习(二)工厂模式——简单工厂模式

设计模式学习&#xff08;二&#xff09;工厂模式——简单工厂模式 前言简单工厂模式简介示例优点缺点使用场景 前言 工厂模式是一种常用的设计模式&#xff0c;属于创建型模式之一。它的主要目的是为了解耦组件之间的依赖关系。通过使用工厂模式&#xff0c;系统中的具体类的…...

贷款业务——LPR、APR、IRR

文章目录 LPR&#xff08;Loan Prime Rate&#xff09;贷款市场报价利率APR&#xff08;Annual Percentage Rate&#xff09;年化百分比利率IRR&#xff08;Internal Rate of Return&#xff09;内部收益率 LPR、APR 和 IRR 是三个不同的金融术语&#xff0c;LPR 是一种市场利率…...

Simscape Multibody与RigidBodyTree:机器人建模

RigidBodyTree&#xff1a;主要用于表示机器人刚体结构的动力学模型&#xff0c;重点关注机器人的几何结构、质量和力矩&#xff0c;以及它们如何随时间变化。它通常用于计算机器人的运动和受力情况。Simscape Multibody&#xff1a;作为Simscape的一个子模块&#xff0c;专门用…...

数据结构刷题-链表

数据结构刷题-链表 总结&#xff1a;1 链表的解法总结&#xff1a; 1 链表的知识点&#xff1a;1 LC链表合集&#xff1a;1.1 lc206反转链表&#xff1a; 双指针&#xff1a;lc25: K个一组翻转链表&#xff1a;栈1.2 lc203移除链表元素&#xff1a;1.3 设计链表&#xff1a;1.4…...

Java应届第一年规划

&#x1f47d;System.out.println(“&#x1f44b;&#x1f3fc;嗨&#xff0c;大家好&#xff0c;我是代码不会敲的小符&#xff0c;目前工作于上海某电商服务公司…”); &#x1f4da;System.out.println(“&#x1f388;如果文章中有错误的地方&#xff0c;恳请大家指正&…...

js之简单轮播图

今天给大家封装一个简单的轮播图,可以点击下一张上一张以及自动轮播 <!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>走马…...

GitLab教程(二):快手上手Git

文章目录 1.将远端代码克隆到本地2.修改本地代码并提交到远程仓库3.Git命令总结git clonegit statusgit addgit commitgit pushgit log 首先&#xff0c;我在Gitlab上创建了一个远程仓库&#xff0c;用于演示使用Gitlab进行版本管理的完整流程&#xff1a; 1.将远端代码克隆到本…...

前端渲染大量数据思路【虚拟列表】【异步机制】

当浏览器遇到性能瓶颈导致页面卡顿时&#xff0c;你会怎么处理&#xff1f;如何查找问题的原因&#xff1f; 浏览器本身自带性能检测工具&#xff0c;通常我们分析由脚本导致的页面卡顿会选择 性能&#xff08;performance&#xff09; 选项卡&#xff0c;在其中我们可以找到导…...

Ubuntu24.04记录网易邮箱大师的安装

邮箱大师下载 官网自行下载&#xff0c;下载后文件名“mail.deb" https://dashi.163.com/ 安装发现缺少依赖 #mermaid-svg-8wqpqFSBVOPD7NGP {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8wqpqFSBVOPD7NGP …...

PDF编辑与转换的终极工具智能PDF处理Acrobat Pro DC

Acrobat Pro DC 2023是一款功能全面的PDF编辑管理软件&#xff0c;支持创建、编辑、转换、签署和共享PDF文件。它具备OCR技术&#xff0c;可将扫描文档转换为可编辑文本&#xff0c;同时提供智能PDF处理技术&#xff0c;确保文件完整性和可读性。此外&#xff0c;软件还支持电子…...

Django UpdateView视图

UpdateView是Django中的一个通用视图&#xff0c;用于处理对象的更新操作。它允许用户更新一个已经存在的对象。UpdateView通常与一个模型表单一起使用&#xff0c;这样用户就可以看到当前对象的值&#xff0c;并可以修改它们。 1&#xff0c;添加视图 Test/app3/views.py fr…...

【CS.SE】2024年,你应该选择计算机专业吗?详细分析与未来展望

文章目录 1. 引言1.1 背景介绍 2. 计算机相关专业的现状与挑战2. 计算机相关专业的现状与挑战2.1 行业内的就业趋势2.1.1 现有就业数据2.1.2 行业需求变化 2.2 市场饱和度与竞争2.2.1 毕业生数量增长2.2.2 薪资与职业发展 2.3 技术创新与行业发展2.3.1 新兴技术的发展2.3.2 全球…...

后端开发面经系列 -- 华为OD -- C++面经(全)

华为OD – C面经&#xff08;全&#xff09; 公众号&#xff1a;阿Q技术站 文章目录 华为OD -- C面经&#xff08;全&#xff09;一面1、C结构体和类的区别&#xff0c;类默认的访问权限&#xff0c;结构体可以定义成员函数吗&#xff1f;2、多态的意义&#xff1f;多态的意义…...

3072. 将元素分配到两个数组中 II Rust 线段树 + 离散化

题目 给你一个下标从 1 开始、长度为 n 的整数数组 nums 。 现定义函数 greaterCount &#xff0c;使得 greaterCount(arr, val) 返回数组 arr 中 严格大于 val 的元素数量。 你需要使用 n 次操作&#xff0c;将 nums 的所有元素分配到两个数组 arr1 和 arr2 中。在第一次操…...

day35|1005.K次取反后最大化的数组和 134. 加油站135. 分发糖果

文章目录 python语法记录 sort格式 1005.K次取反后最大化的数组和思路方法一方法二 按照绝对值排序 教程&#x1f388;✨ 背住 按照绝对值进行降序排序的语法是&#xff1a; 134. 加油站思路方法一 教程解法方法二 暴力求解 135. 分发糖果思路方法一 总结 python语法记录 sort …...

HWA和BSS区别

芯片中的HWA&#xff08;Hardware Accelerator&#xff09;模块功能主要是为了加速雷达信号处理的特定任务。HWA模块在雷达系统中起到关键作用&#xff0c;以下是其主要功能和作用&#xff1a; 信号预处理&#xff1a; 滤波&#xff1a;对接收到的雷达信号进行滤波&#xff0c;…...

【Excel】Excel中将日期格式转换为文本格式,并按日期显示。

【问题需求】 在使用excel进行数据导入的过程中&#xff0c; 有的软件要求日期列必须是文本格式。 但是直接将日期列的格式改为文本后&#xff0c;显示一串数字&#xff0c;而不按日期显示。 进而无法导入使用。 【解决方法】 使用【TXET】函数公式进行处理&#xff0c; 在单…...

物联网学习小记

https://www.cnblogs.com/senior-engineer/p/10045658.html GOSP: 提供类似Qt的API接口&#xff0c;仅需要几百KB的硬件资源&#xff08;比Qt小的多&#xff09;&#xff0c;能运行在Qt不支持的低配置硬件上&#xff08;对Qt生态形成补充&#xff09;&#xff0c;适用于嵌入式…...

代码随想录-Day29

491. 非递减子序列 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情…...

C/C++ 进阶(6)红黑树

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C 目录 一、概念 性质 二、操作 插入 情况一&#xff1a;cur为红、p为红、g为黑&#xff0c;如果u存在且为红 步骤&#xff1a; 情况二&#xff1a;cur为红、p为红、g为黑&#xff0c;如果u不存在或…...

【Vue】构建vuex-cart模块

说明&#xff1a;既然明确数据要存 vuex&#xff0c;建议分模块存&#xff0c;购物车数据存 cart 模块&#xff0c;将来还会有 user 模块&#xff0c;article 模块… 新建 store/modules/cart.js 挂载到 vuex 仓库上 store/cart.js import Vue from vue import Vuex from vu…...

如何成为嵌入式系统工程师?

各位朋友&#xff0c;如果你们有意向投身于嵌入式开发领域&#xff0c;那么强烈建议你们在软件和硬件两个方面均展开深入且全面的学习。 嵌入式计算机作为嵌入式系统的核心技术支撑&#xff0c;其是直接面向用户、产品以及应用的&#xff0c;无论是软件还是硬件方面都能发挥重要…...

【AI大模型】Transformers大模型库(七):单机多卡推理之device_map

目录​​​​​​​ 一、引言 二、单机多卡推理之device_map 2.1 概述 2.2 自动配置&#xff0c;如device_map"auto" 2.3 手动配置&#xff0c;如device_map"cuda:1" 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库&#x…...

驱动代码编写(一)

驱动程序的作用 驱动程序是指与硬件设备和操作系统进行通信的软件。它的主要功能有以下几个方面&#xff1a; 提供硬件支持&#xff1a;驱动程序允许操作系统与硬件设备进行通信&#xff0c;以便正确地操作和控制硬件设备。它可以向操作系统提供有关硬件设备的各种信息&#x…...

Prompt-to-Prompt Image Editing with Cross Attention Control

Prompt-to-Prompt Image Editing with Cross Attention Control (P2P) Amir Hertz, Tel Aviv University, ICLR23, Paper, Code 1. 前言 编辑对这些生成模型来说是具有挑战性的&#xff0c;因为编辑技术的一个固有特性是保留大部分原始图像&#xff0c;而在基于文本的模型中…...

实验11 OSPF协议配置

实验11 OSPF协议配置 一、OSPF单区域配置&#xff08;一&#xff09;原理描述&#xff08;二&#xff09;实验目的&#xff08;三&#xff09;实验内容&#xff08;四&#xff09;实验配置&#xff08;五&#xff09;实验步骤 二、OSPF多区域配置&#xff08;一&#xff09;原理…...

北京网站制作飞沐/b站视频推广

16 网关 16.1 概念 服务治理&#xff0c;服务注册发现&#xff0c;服务调用&#xff0c;熔断。已经学完。 微服务基本模块已经有了&#xff0c;也可以做微服务了。但完成一个复杂的业务&#xff0c;可能需要多个微服务合作来完成&#xff0c;比如下单&#xff0c;需要用户服…...

政府类网站建设费用/怎样开网站

Curl是Linux下一个非常强大的http命令行工具&#xff0c;其功能十分强大。一、CURL对HTTP的常规訪问1. 訪问站点$ curl http://www.linuxidc.com回车之后。www.linuxidc.com 的html 显示在屏幕上了 2. 保存页面用curl option: -o$ curl -o page.html http://www.linuxidc.com能…...

信息课做网站的软件/企业邮箱登录

idea新建xml文件https://www.jianshu.com/p/b8aeadae39b0        或https://blog.csdn.net/Hi_Boy_/article/details/80491358一.##Xml概念>eXtendsible markup language 可扩展的标记语言二.###XML 作用&#xff1a;1. 可以用来保存数据2. 可以用来做配置文件3. …...

浙江建设网查询/网络优化工程师招聘信息

原文:WPF线性渐变画刷应用之——炫彩线条效果图&#xff1a; Xaml代码&#xff1a; <Rectangle Width"800" Height"10">  <Rectangle.Fill>    <LinearGradientBrush StartPoint"0,0" EndPoint"1,1">    …...

购物网站开发 webstorm/网页设计与网站开发

之前我们讲解了Git在本地版本库中的基本操作&#xff0c;这些操作和Linux系统中的操作基本相同。之后&#xff0c;在上一篇中&#xff0c;我们记述了如何获得SSH密钥&#xff0c;以及如何与Github连接的问题。在这些准备工作做好了之后&#xff0c;我们尝试使用Github。 本文使…...

平顶山市建设局网站/百度竞价排名案例分析

标题: A Robust Laser-Inertial Odometry and Mapping Method for Large-Scale Highway Environments作者: Shibo Zhao, Zheng Fang, HaoLai Li, Sebastian Scherer1摘要我们提出了一种新的激光惯性里程计和建图方法,以实现大规模公路环境中的实时、低漂移和鲁棒的位姿估计.该方…...