SpringMVC 中的异常体系知识点梳理

1.异常解析器概览

在 SpringMVC 的异常体系中,处于最顶层的大 Boss 是 HandlerExceptionResolver,这是一个接口,里边只有一个方法:


  1. public interface HandlerExceptionResolver { 
  2.  @Nullable 
  3.  ModelAndView resolveException( 
  4.    HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex); 

resolveException 方法就用来解析请求处理过程中所产生的异常,并最终返回一个 ModelAndView。

我们来看下 HandlerExceptionResolver 的实现类:

直接实现 HandlerExceptionResolver 接口的类有三个:

  • HandlerExceptionResolverComposite:这个一看又是一个组合,在最近的源码分析中我们已经多次见到 xxxComposite 了,这里就不再赘述。
  • DefaultErrorAttributes:这个用来保存异常属性。
  • AbstractHandlerExceptionResolver:这个的子类比较多:

    • SimpleMappingExceptionResolver:通过提前配置好的异常类和 View 之间的对应关系来解析异常。
    • AbstractHandlerMethodExceptionResolver:处理使用 @ExceptionHandler 注解自定义的异常类型。
    • DefaultHandlerExceptionResolver:按照不同类型来处理异常。
    • ResponseStatusExceptionResolver:处理含有 @ResponseStatus 注解的异常。

在 SpringMVC 中,大致的异常解析器就是这些,接下来我们来逐个学习这些异常解析器。

2.AbstractHandlerExceptionResolver

AbstractHandlerExceptionResolver 是真正干活的异常解析器的父类,我们就先从他的 resolveException 方法开始看起。


  1. @Override 
  2. @Nullable 
  3. public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { 
  4.  if (shouldApplyTo(request, handler)) { 
  5.   prepareResponse(ex, response); 
  6.   ModelAndView result = doResolveException(request, response, handler, ex); 
  7.   if (result != null) { 
  8.    logException(ex, request); 
  9.   } 
  10.   return result; 
  11.  } 
  12.  else { 
  13.   return null
  14.  } 
  1. 首先调用 shouldApplyTo 方法判断当前解析器是否可以处理传入的处理器所抛出的异常,如果不支持,则直接返回 null,这个异常将交给下一个 HandlerExceptionResolver 去处理。
  2. 调用 prepareResponse 方法处理 response。
  3. 调用 doResolveException 方法实际处理异常,这是一个模版方法,具体的实现在子类中。
  4. 调用 logException 方法记录异常日志信息。

记录异常日志没啥好说的,doResolveException 则是一个空的模版方法,所以这里对我们来说主要就是两个方法:shouldApplyTo 和 prepareResponse,我们分别来看。

shouldApplyTo


  1. protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { 
  2.  if (handler != null) { 
  3.   if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) { 
  4.    return true
  5.   } 
  6.   if (this.mappedHandlerClasses != null) { 
  7.    for (Class<?> handlerClass : this.mappedHandlerClasses) { 
  8.     if (handlerClass.isInstance(handler)) { 
  9.      return true
  10.     } 
  11.    } 
  12.   } 
  13.  } 
  14.  return !hasHandlerMappings(); 

这里涉及到了两个对象:mappedHandlers 和 mappedHandlerClasses:

  • mappedHandlers:存储的是处理器对象(Controller 或者 Controller 中的方法)
  • mappedHandlerClasses:存储的是处理器的 Class。

我们在配置异常解析器的时候可以配置这两个对象,进而实现该异常处理器只为某一个处理器服务,但是一般来说没这种需求,所以大家仅做了解即可。

如果开发者一开始配置了 mappedHandlers 或者 mappedHandlerClasses,则用这两个和处理器去比较,否则就直接返回 true,表示支持该异常处理。

prepareResponse

prepareResponse 方法比较简单,主要是处理一下响应头的缓存字段。


  1. protected void prepareResponse(Exception ex, HttpServletResponse response) { 
  2.  if (this.preventResponseCaching) { 
  3.   preventCaching(response); 
  4.  } 
  5. protected void preventCaching(HttpServletResponse response) { 
  6.  response.addHeader(HEADER_CACHE_CONTROL, "no-store"); 

这是 AbstractHandlerExceptionResolver 的大致内容,可以看到还是非常 easy 的,接下来我们来看它的实现类。

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章