Spring Boot系列十一 从源码的角度理解Spring MVC异常处理原理

本文从源码层面探讨Spring MVC的异常处理原理,包括HandlerExceptionResolver接口及其常用实现类,如ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver的工作方式。同时,介绍了Spring MVC启动时如何初始化HandlerExceptionResolver,以及DispatcherServlet的异常处理流程。
摘要由CSDN通过智能技术生成

1. 概述

上一篇文章Spring Boot系列十 Spring MVC全局异常处理总结介绍了如何在Spring MVC中实现对异常的处理,本文从源码角度理解Spring MVC异常处理原理,主要包括如下内容:

  • HandlerExceptionResolver以及常用实现类,理解默认实现HandlerExceptionResolver的用处和源码解读
  • Ordered接口及如何自定义HandlerExceptionResolver
  • Spring MVC 异常处理HandlerExceptionResolver对象初始化和处理流程的源码解读

2. HandlerExceptionResolver以及常用实现类

2.1 HandlerExceptionResolver接口

HandlerExceptionResolver是一个接口,用于处理网络请求过程中抛出的异常,但是不处理异常本身抛出的异常和视图解析过程中抛出的异常

下图是Spring MVC默认实现的HandlerExceptionResolver类
这里写图片描述

2.2. HandlerExceptionResolverComposite

Spring Boot启动时会默认注册HandlerExceptionResolverComposite对象。此类只是一个组合类,并不进行真正的异常处理。当他捕获异常时他只是将异常轮询委托给注册到它属性里的上的HandlerExceptionResolver类来处理异常,如果处理的结果不为null,则转给下一个处理

@Override
public ModelAndView resolveException(HttpServletRequest request,
     HttpServletResponse response,
     Object handler,
     Exception ex) {
    if (resolvers != null) {
        for (HandlerExceptionResolver handlerExceptionResolver : resolvers) {
            ModelAndView mav = handlerExceptionResolver.resolveException(request, response, handler, ex);
            if (mav != null) {
                return mav;
            }
        }
    }
    return null;
}

默认注册到HandlerExceptionResolverComposite 的属性有以下3个HandlerExceptionResolver,按照优先级排列如下:

  • ExceptionHandlerExceptionResolver
  • ResponseStatusExceptionResolver
  • DefaultHandlerExceptionResolver

下面详细介绍这3个HandlerExceptionResolver的作用

2.3. ExceptionHandlerExceptionResolver

使用@ExceptionHandler注解方法处理异常类,我们之前介绍的使用注解处理异常就有这个类的功劳。默认情况下,这个HandlerExceptionResolver的优先级是最高。
以下是ExceptionHandlerExceptionResolver运行时属性值
这里写图片描述
属性exceptionHandlerAdviceCache :存储@Controller里@ExceptionHandler的方法
属性exceptionHandlerAdviceCache:存储@ControllerAdvice里@ExceptionHandler的全局方法

处理异常的关键代码
入口doResolveHandlerMethodException方法会通过 getExceptionHandlerMethod获取对应的@ExceptionHandler方法,如果有找到则执行此方法

    @Override
    protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
            HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
        // 杳找对应的方法@ExceptionHandler
        ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
        if (exceptionHandlerMethod == null) {
            return null;
        }
....
            if (cause != null) {
                // 执行异常处理方法
                exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod);
            }
            else {
                // 执行异常处理方法
                exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, handlerMethod);
            }
        }
....
    }

getExceptionHandlerMethod方法:查找特定异常的@ExceptionHandler方法,首先从抛出异常的@Controller类中寻找对应的处理方法,如果没有再从@ControllerAdvice中查找全局的@ExceptionHandler方法,如果找到,则调用这个方法执行处理,否则返回null

protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) {
    Class<?> handlerType = (handlerMethod != null ? handlerMethod.getBeanType() : null);

    if (handlerMethod != null) {
        // 从抛出异常的@Controller类中自身中寻找对应的处理方法,如果有找到先缓存
        ExceptionHandlerMethodRes
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值