环境:Springboot3.0.5
概述如果在请求映射期间发生异常或从请求处理程序(例如@Controller)抛出异常,DispatcherServlet将委托给HandlerExceptionResolver
(资料图片仅供参考)
下表列出了可用的HandlerExceptionResolver实现。
HandlerExceptionResolver实现类:
HandlerExceptionResolver | 描述 |
SimpleMappingExceptionResolver | 异常类名和错误视图名之间的映射。用于在浏览器应用程序中渲染错误页面。 |
DefaultHandlerExceptionResolver | 解析Spring MVC引发的异常,并将其映射为HTTP状态码。 |
ResponseStatusExceptionResolver | 使用@ResponseStatus注解解析异常,并根据注解中的值将异常映射为HTTP状态码。 |
ExceptionHandlerExceptionResolver | 通过在@Controller或@ControllerAdvice类中调用由@ExceptionHandler注释的方法来解决异常。 |
我们可以声明多个HandlerExceptionResolver
HandlerExceptionResolver的约定规定它可以返回:
指向错误视图的ModelAndView。如果异常是在解析器中处理的,则返回空的ModelAndView。如果异常仍然未解决,则为null,以便后续的解析器尝试,如果异常在最后仍然存在,则允许它向上冒泡到Servlet容器。Controller接口调用原理SpringMVC请求入口通过DispatcherServlet执行大致核心流程如下:
首先通过HandlerMapping确定目标Handler对象(如果接口是Controller那么这里会是HandlerMethod)通过上一步Handler对象,确定执行真正调用的HandlerAdapter这里以Controller接口为例,HandlerAdapter对象为RequestMappingHandlerAdapter
DispatcherServletpublic class DispatcherServlet extends FrameworkServlet { protected void doDispatch(...) throws Exception { HandlerExecutionChain mappedHandler = null; try { Exception dispatchException = null; // 根据请求确定Handler对象(遍历所有的HandlerMapping) mappedHandler = getHandler(processedRequest); // 根据上一步确定的Handler对象,确定HandlerAdapter对象 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 真正执行目标方法的调用 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { dispatchException = new ServletException("Handler dispatch failed: " + err, err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }}RequestMappingHandlerAdapterpublic class RequestMappingHandlerAdapter { protected ModelAndView handleInternal(...) throws Exception { ModelAndView mav; mav = invokeHandlerMethod(request, response, handlerMethod); } protected ModelAndView invokeHandlerMethod(...) throws Exception { // ... ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); // ... 对ServletInvocableHandlerMethod进行配置 invocableMethod.invokeAndHandle(webRequest, mavContainer); return getModelAndView(mavContainer, modelFactory, webRequest); }}ServletInvocableHandlerMethod执行参数解析目标Controller方法调用及返回值的处理
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { public void invokeAndHandle(...) throws Exception { // 该方法中会进行请求参数的解析及目标方法的调用 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); // ... try { // 处理返回值 this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { throw ex; } }}通过上面的源码分析,在调用过程中如果发生了异常会将异常直接抛出,在DispatcherServlet中会进行异常的处理。
异常解析原理分析接着上面的源码分析,当发生异常后最终会在DispatcherServlet#processDispatchResult方法中进行处理。
public class DispatcherServlet extends FrameworkServlet { /* * 默认情况下有如下2个异常解析器 * 1. DefaultErrorAttributes * 2. ExceptionHandlerExceptionResolver */ private List handlerExceptionResolvers; private void processDispatchResult(...) { if (exception != null) { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); // 处理异常 mv = processHandlerException(request, response, handler, exception); } } protected ModelAndView processHandlerException(...) throws Exception { ModelAndView exMv = null; if (this.handlerExceptionResolvers != null) { // 遍历所有的异常解析器 for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) { // 解析异常,核心的解析器是ExceptionHandlerExceptionResolver exMv = resolver.resolveException(request, response, handler, ex); } } // ... }} ExceptionHandlerExceptionResolver类继承自AbstractHandlerMethodExceptionResolver该类又继承自AbstractHandlerExceptionResolver
// 调用父类(AbstractHandlerExceptionResolver)方法public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered { public ModelAndView resolveException(...) { // doResolveException该方法在子类AbstractHandlerMethodExceptionResolver中重写 ModelAndView result = doResolveException(request, response, handler, ex); }}AbstractHandlerMethodExceptionResolver
public abstract class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExceptionResolver { protected final ModelAndView doResolveException(...) { HandlerMethod handlerMethod = (handler instanceof HandlerMethod hm ? hm : null); return doResolveHandlerMethodException(request, response, handlerMethod, ex); }}ExceptionHandlerExceptionResolver
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver implements ApplicationContextAware, InitializingBean { protected ModelAndView doResolveHandlerMethodException(...) { // 该方法中会先从当前的Controller中查找是否有@ExceptionHandler注解的方法(如果匹配) // 如果没有再从全局的异常处理类句柄中查找 ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception); if (exceptionHandlerMethod == null) { return null; } // 执行异常处理方法的调用 exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, arguments); } protected ServletInvocableHandlerMethod getExceptionHandlerMethod(...) { Class> handlerType = null; if (handlerMethod != null) { handlerType = handlerMethod.getBeanType(); // 缓存并设置当前执行Class对应的ExceptionHandlerMethodResolver // ExceptionHandlerMethodResolver构造函数中会解析当前类中的所有方法是否有@ExceptionHandler注解 ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.computeIfAbsent(handlerType, ExceptionHandlerMethodResolver::new); // 解析是否匹配当前发生的异常 Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method, this.applicationContext); } } // 如果上面的执行的Class中没有找到对应处理器,那么就从全局的异常处理中进行查找匹配 // 这里的exceptionHandlerAdviceCache集合在类初始化执行时已经处理完成 for (Map.Entry entry : this.exceptionHandlerAdviceCache.entrySet()) { ControllerAdviceBean advice = entry.getKey(); if (advice.isApplicableToBeanType(handlerType)) { ExceptionHandlerMethodResolver resolver = entry.getValue(); Method method = resolver.resolveMethod(exception); if (method != null) { return new ServletInvocableHandlerMethod(advice.resolveBean(), method, this.applicationContext); } } } return null; }} 通过上面的源码分析你应该知道了关于SpringMVC中异常处理的原理。
当上面的异常处理机制都没法处理,那么将会调用默认的/error接口。
public class ErrorMvcAutoConfiguration { @Bean @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT) public BasicErrorController basicErrorController(ErrorAttributes errorAttributes, ObjectProvider errorViewResolvers) { return new BasicErrorController(errorAttributes, this.serverProperties.getError(), errorViewResolvers.orderedStream().toList()); } } BasicErrorController@Controller@RequestMapping("${server.error.path:${error.path:/error}}")public class BasicErrorController extends AbstractErrorController {}上面的错误接口/error在容器启动时会自动注册到内嵌的容器中,如:Tomcat。
标签:
详解SpringBoot接口异常处理机制及源码分析_今日精选 环境:Springboot3 0 5概述如果在请求映射期间发生异常或从请求处理程
电报解读|AI促光通信产业高速发展 薄膜铌酸锂潜在市场空间接近百亿 精品VIP投研内容
西湖划船刺客运营方被罚12万 西湖“划船刺客”事件最新进展! 近日,杭州西湖风景名胜区国有资本投资运营有限公司因消费侵权行为,被
佐力药业(300181.SZ):2022年度乌灵系列营业收入达10.92亿元|全球热头条 格隆汇6月15日丨佐力药业300181300181SZ召开线上会议就乌灵系列的收入
拼多多客服账号怎么进行创建?拼多多客服外包平台怎么加入? 拼多多客服账号怎么进行创建?登录拼后台点击设置子账号管理,在右
详解SpringBoot接口异常处理机制及源码分析_今日精选 环境:Springboot3 0 5概述如果在请求映射期间发生异常或从请求处理程
木雕、砖雕、面具、唐卡……尼泊尔手工艺品展亮相三亚 近日,第三届南山非遗节正在三亚南山文化旅游区火热进行中,海南省非遗
火星报创办时间什么时候?火星报创办背景是什么? 火星报创办时间什么时候?1900年12月24日,火星报是由列宁领导的,俄
理财没到期急用钱怎么办?钱存了理财没到期可以取出来吗? 每日速看 在理财过程中,有时候投资者可能会遇到紧急的资金需求,而此时投资
环球热推荐:琼港新企业交流中心落户三亚 6月13日,海南自由贸易港(三亚)新加坡投资交流会在新加坡举行,市投
5万级超高性价比小车,瑞虎3x拼多多专属电商版上线,价格一卷到底 通过电商平台购买汽车产品,已成为年轻人喜闻乐见的消费形式,而汽车厂商也都乐于携手电商平台,以更多的实惠和惊喜,来提升用户的消费和服
京东物流落成全球规模最大仓拣一体智能物流园区 一箱刚从苏州蟹塘现捕现捞的“六月黄”(临近成熟的大闸蟹)14日从京东物
电动皮卡 怎么突然就行了? 全球快讯 电动皮卡怎么突然就行了?
高速错过出口 丰田亚洲龙缓行被大货车追尾致5死 官方:两司机均分心驾驶-环球简讯 高速错过出口丰田亚洲龙缓行被大货车追尾致5死官方:两司机均分心驾驶
极萌Jmoon带来变美科技新革命 极萌Jmoon,作为一家专注于极速美容科技的公司,一直在持续进行着市场调研和技术创新。重视产品的质量和行业标准,致力于推动行业朝着标准
茶杯犬一岁等于人的几岁? 茶杯犬的缺点有哪些?_最新资讯 现在很多家庭都会养宠物,而小狗就是家庭宠物的选择之一,狗的品种
FOF基金有什么优势?私募基金和公募基金谁收益更高? FOF基金有什么优势?1 解决基金产品筛选难题。目前国内公募基金数量
香瓜种植时间和方法是什么?香瓜热量高吗减肥期间能吃吗?-世界播资讯 香瓜种植时间和方法是什么?香瓜的种植时间是每年的8~10月份。香瓜种
焦点热文:三亚建立“热线+督查+制度” 三位一体破难题机制 日前,三亚多部门联合下发《关于建立“热线+督查+制度”三位一体同推互
选址日报:三星投215亿建生产基地;诺和诺德斥164亿扩建工厂 三星投215亿建生产基地据最新消息,三星旗下负责电池和电子材料制造的
天天亮点!装700件快递大货车高速爆胎翻车 车轮花纹都磨没了 装700件快递大货车高速爆胎翻车车轮花纹都磨没了
热讯:小米14设计定了:标准版小直屏 Pro版极窄微曲屏 (相关资料图)6月15日消息,高通今年的骁龙技术峰会提前到10月份,这
三亚划定21个城市更新片区 以天涯区和吉阳区的老城片区为主_天天热点评 日前,《三亚市中心城区城市更新专项规划》(以下简称《规划》)出炉,
基金定投选择哪种基金?基金存在的风险有哪些? 基金定投应该选择什么样的基金?1 波动大基金定投的收益主要是通过微
时讯:背书转让的限制主要有哪些?背书转让具有哪些法律效力? 背书转让的限制主要有哪些?(1)出票人在汇票上记载不得转让字样的,
每日看点!“期待更多有志青年返乡创业”(帮扶县驻村手记) 走进河南省商丘市虞城县大侯镇聂楼村产业园的一家箱包厂,敞亮的车间里
谷歌推出多项功能:识别皮肤病、模拟试穿衣服
当前视点 IT之家6月15日消息,谷歌近日宣布了一系列新的搜索更新,涵盖了旅游规
5万级超高性价比小车,瑞虎3x拼多多专属电商版上线,价格一卷到底 通过电商平台购买汽车产品,已成为...
天猫国际支付方式有云闪付吗?天猫国际用户购买须知是啥意思? 天猫国际支付方式有云闪付吗?有一...
极萌Jmoon带来变美科技新革命 极萌Jmoon,作为一家专注于极速美...
木雕、砖雕、面具、唐卡……尼泊尔手工艺品展亮相三亚 近日,第三届南山非遗节正在三亚南...
清淤疏浚 改善水质 6月14日,在三亚河上,工作人员正...
环球热推荐:琼港新企业交流中心落户三亚 6月13日,海南自由贸易港(三亚)...
焦点热文:三亚建立“热线+督查+制度” 三位一体破难题机制 日前,三亚多部门联合下发《关于建...
膏药代加工发展迎来新机遇 仙佑集团质量严把关受关注-天天即时 作为国内知名的膏药代加工企业之一...
互联网+医疗助力研发投入 郑州膏药代加工保障质量安全 作为国内知名的膏药代加工企业之一...
斥资226亿元,TI将在马来西亚新建两座工厂 6月13日,德州仪器(TI)宣布将在...
互联网+医疗助力研发投入 郑州膏药代加工保障质量安全 作为国内知名的膏药代加工企业之一...
不良信用记录包括什么?不良信用记录几年可以消除?-全球即时看 不良信用记录包括什么?不良信用记...
腾讯有意全资收购搜狗 王小川是怎么回应的? 天天观察 腾讯有意全资收购搜狗搜狗公告显示...
天天百事通!提取约翰・列侬声音 披头士借助AI发行最后一曲 (相关资料图)据BBC报道,即将迎来8...
为困境未成年人提供家庭教育指导 为了促进家庭教育的科学化、规范化...
今亮点!只要钱够多 哪怕危险行业狮子座也会勇敢尝试? 金牛座:钱是最重要的金牛座是出了...
世界今亮点!徐州泉山:“微改造”助力“大文明” “微环境”塑造“微幸福” “今天好开心,我连闯三关!”近日...
全球信息:散户和机构投资者的资金实力一样吗?散户和机构投资者的作用一样吗? 散户和机构投资者的资金实力一样吗...
荷兰猪的寿命有多长 ?荷兰猪简介_当前热议 荷兰猪其实指的就是豚鼠,又叫天竺...
环球速讯:退休后如何存钱收益高?老年人怎么理财合适? 很多老人退休后喜欢做资产规划,如...
环球观天下!仓鼠怀孕了怎么办?仓鼠怀孕有什么特征呢? 大部分人都有养小仓鼠的经历吧,仓...
天天通讯!整存整取起存金额多少 ?整存整取可以提前取吗? 银行定期存款包括整存整取、整存零...
临近抄底现象是什么(股票抄底是什么意思)|当前通讯 临近抄底现象是什么(散户为什么喜...
国家统计局:1-5月商品房销售额同比增长8.4% 6月15日,国家统计局发布了1-5月份...
房屋保险一年多少钱?房屋保险怎么买划算? 房屋保险一年多少钱?不同的产品自...
热点聚焦:膏药谋求高质量发展 河南仙佑膏药代加工产业升级 作为国内知名的膏药代加工企业之一...
膏药谋求高质量发展 河南仙佑膏药代加工产业升级 作为国内知名的膏药代加工企业之一...
招商银行周周宝赎回几天到账?招行理财利率是多少? 焦点关注 现在各大银行也相继推出了很多理财...
天猫国际支付方式有云闪付吗?天猫国际用户购买须知是啥意思? 天猫国际支付方式有云闪付吗?有一...
世界新消息丨真刑!借“总部经济”之名,开709家空壳公司,伪装产业集群 正义网近日披露了一宗借“总部经济...
整合旗下国有投资平台 杭州打出“3000亿产业基金集群”王牌 环球报道 又一个千亿母基金群来了。今日,杭...
合金弹头如何调节灵敏度?合金弹头速度太快怎么调?|新消息 合金弹头如何调节灵敏度?打开游戏...
理财产品工作日可申赎是什么意思?申赎和买卖有什么区别?|世界看点 购买理财产品的时候,投资者会看理...
隔夜回购操作是什么意思?隔日回购协议的基本内容是什么? 隔夜回购操作是什么意思?隔夜回购...
焦点短讯!谷歌将生成式 AI 应用于在线购物,真人模特可实现高精度虚拟换衣
IT之家6月15日消息,谷歌昨日宣布...