一 . 概述
标准的mvc框架都有一个异常处理机制,springmvc同样也提供了一个处理的方式.
在之前的源码之中,我们看到了springmvc统一获取了异常,也就是说springmvc获得了统一处理异常的方式.
二 . 异常处理器
在springmvc之中,将统一的异常处理交给了异常处理器.
我们首先看一下异常处理器的结构:
public interface HandlerExceptionResolver { ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); }
其中有一个核心的方法,我们从参数之中就可以看出,几乎处理异常所需要的所有的参数都拥有了.
三 .自定义异常处理器
上面我们看到了springmvc的跟接口,我们就自定义一个异常处理器.
public class InnerExecptionHandler implements HandlerExceptionResolver{ @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println(ex); return null; } }
我们将上面的处理器配置到springmvc配置文件之中.
<bean class="com.trek.execptionHandler.InnerExecptionHandler"> </bean>
@RequestMapping("/exception") public String exception() { int i = 1/ 0 ; return "/WEB-INF/jsp/success.jsp"; }
现在当我们请求时,我们会发现出现了异常在控制台会有打印了.
那个打印的语句就是异常处理器完成的.
四 .原理分析
springmvc容器在加载的时候,会初始化异常解析器.
protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
我们进入代码之中:
if (this.detectAllHandlerExceptionResolvers) { // Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts. Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values()); // We keep HandlerExceptionResolvers in sorted order. AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers); } }
springmvc会寻找所有的HandlerExceptionResolver的子类,加入到异常处理器之中.
当出现异常的时候,我们看源码:
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } }
我们看到这里统一对异常进行了处理,会调用processHandlerException()方法.
这个方法的核心就是从所有的注册的异常解析器之中获取,然后依次尝试进行处理.