享读SpringMVC源码5-异常处理HandlerExceptionResolver(上)

简介: 享读SpringMVC源码5-异常处理HandlerExceptionResolver(上)

异常是避免不了的的。我们能做的就是减少异常, 以及做好异常的处理。

本文说说SpringMVC中的异常处理。


1.场景分析


我们在写业务代码时,多多少少会自发的做一些异常的捕获,或者处理。

这里有两个问题:

  • 你不可能处理到大多数异常
  • 大量的try catch代码充斥在业务代码中


2.Servlet+tomcat时代


在Servlet+tomcat时代, 异常的统一处理通过在web.xml中配置的。

<!-- 根据状态码 -->
<error-page>
    <error-code>500</error-code>
    <location>/500.jsp</location>
</error-page>
<!-- 根据异常类型 -->
<error-page>
    <exception-type>java.lang.RuntimeException</exception-type>
    <location>/500.jsp</location>
</error-page>


3.springmvc时代


在SpringMVC时代,得意于SpringMVC的中心化思想,所有请求走DispatcherServlet分发器。在DispatcherServlet里可以做一个统一的异常捕获与处理。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        try {
            ModelAndView mv = null;
            Exception dispatchException = null;
            try {
                分发请求,去调用业务逻辑
            }
            catch (Exception ex) {
                dispatchException = ex;//捕获异常
            }
            catch (Throwable err) {//捕获错误
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            //结果处理或者异常处理
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }

处理流程:

  1. 当业务代码抛出异常时,被捕获后,赋值给一个dispatchException变量。然后调用processDispatchResult去处理
  2. processDispatchResult中,异常的处理是调用processHandlerException(request, response, handler, exception)方法。此方法内会遍历所有的异常处理器,找到一个可以处理当前异常的异常处理器
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
            Object handler, Exception ex) throws Exception {
        for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
            exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
            if (exMv != null) {
                break;
            }
        }
}

可以看到异常的处理是由SpringMVC的一个组件HandlerExceptionResolver来处理的。

这就引出了本文的中心,异常处理器HandlerExceptionResolver


4.核心HandlerExceptionResolver


此组件只专门用来处理异常的组件,

HandlerExceptionResolver接口只有一个异常解析的方法定义。

ModelAndView resolveException(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

springMVC为其提供了多个实现


image.png


这里主要的是AbstractHandlerExceptionResolver分支下,是处理异常的各个实现类:


AbstractHandlerExceptionResolver:

此抽象类,不但实现了resolveException方法,而且还提供了额外的方法

  • shouldApplyTo : 匹配逻辑,用于判断当前异常处理器支持那种类型的异常处理


4.1分类
  • SimpleMappingExceptionResolver:简单映射,异常处理。根据异常类型匹配到一个视图处理
  • ResponseStatusExceptionResolver:若抛出的异常类型上有@ResponseStatus注解,此处理器会处理,根据注解的内容,返回相应的HTTP Status Code和内容给客户端【@ResponseStatus标注在异常类上此处理器才会处理】
  • AnnotationMethodHandlerExceptionResolver和ExceptionHandlerExceptionResolver:用来支持ExceptionHandler注解,使用被ExceptionHandler注解所标记的方法来处理异常。其中AnnotationMethodHandlerExceptionResolver在3.0版本中开始提供,ExceptionHandlerExceptionResolver在3.1版本中开始提供,从3.2版本开始,Spring推荐使用ExceptionHandlerExceptionResolver。高阶用法
  • DefaultHandlerExceptionResolver:默认的异常处理器,能处理springMVC大部分异常,也是springmvc默认装配的异常处理器。最常用

https://www.cnblogs.com/xinzhao/p/4902295.html


4.2异常处理器的初始化

异常的初始化伴随着DispatcherServlet的初始化

DispatcherServlet
protected void initStrategies(ApplicationContext context) {
        。。。
        initHandlerExceptionResolvers(context);
        。。。
}

异常初始化策略:

(1. detectAllHandlerExceptionResolvers 为true时从容器内获取所有实现了ExceptionResolver接口的bean,并根据其order属性排序,依次调用


(2.detectAllHandlerExceptionResolvers=false时,只获取handlerExceptionResolver的bean作为异常处理器


(3.上属两种还找不到异常处理器的情况下,默认加载配置文件中的处理器

默认的异常处理bean定义在DispatcherServlet.properties

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver


相关文章
|
11月前
|
容器
SpringMVC常见组件之HandlerExceptionResolver分析-2
SpringMVC常见组件之HandlerExceptionResolver分析-2
66 0
|
6月前
|
Java 应用服务中间件 Spring
Spring5源码(50)-SpringMVC源码阅读环境搭建
Spring5源码(50)-SpringMVC源码阅读环境搭建
76 0
|
3月前
|
前端开发 Java Spring
SpringMVC种通过追踪源码查看是哪种类型的视图渲染器(一般流程方法)
这篇文章通过示例代码展示了如何在Spring MVC中编写和注册拦截器,以及如何在拦截器的不同阶段添加业务逻辑。
SpringMVC种通过追踪源码查看是哪种类型的视图渲染器(一般流程方法)
|
存储 前端开发 搜索推荐
(八)Spring源码解析:Spring MVC
(八)Spring源码解析:Spring MVC
95 1
|
6月前
|
Java 应用服务中间件 数据库连接
Spring5源码(51)-Servlet知识点回顾以及SpringMVC分析入口
Spring5源码(51)-Servlet知识点回顾以及SpringMVC分析入口
65 0
|
6月前
|
SQL JSON 前端开发
【源码免费下载】SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统
【源码免费下载】SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统
107 0
|
6月前
|
设计模式 前端开发 Java
[Spring ~源码] Spring的run方法以及SpringMVC执行流程
[Spring ~源码] Spring的run方法以及SpringMVC执行流程
|
11月前
|
JSON 前端开发 Java
SpringMVC常见组件之HandlerExceptionResolver分析-1
SpringMVC常见组件之HandlerExceptionResolver分析-1
177 0
|
前端开发 Java Spring
源码浅析SpringMVC请求的流转过程
Spring MVC框架使用了其”模型-视图-控制器”( Model-View-Controller )架构方式,用于开发灵活且松散耦合的 Web 应用程序。我们都使用过SpringMVC来处理信息,并渲染视图到Browser。但需要注意的是,在现在的架构中,大都采用了前后端分离的情况,而我们在使用SpringMVC的时候,只需要关注M(Model),C(Controller)这两个部分,而视图渲染的部分则交给了前端。
322 0
源码浅析SpringMVC请求的流转过程
|
JSON 缓存 Java
享读SpringMVC源码5-异常处理HandlerExceptionResolver(下)
享读SpringMVC源码5-异常处理HandlerExceptionResolver(下)