// Success and error responses may use different content types // 移除 PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE 属性 request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
// Check registered HandlerExceptionResolvers... // 遍历 HandlerExceptionResolver 数组,解析异常,生成 ModelAndView 对象 ModelAndViewexMv=null; if (this.handlerExceptionResolvers != null) { // 遍历 HandlerExceptionResolver 数组 for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) { // 解析异常,生成 ModelAndView 对象 exMv = resolver.resolveException(request, response, handler, ex); // 生成成功,结束循环 if (exMv != null) { break; } } } // 情况一,生成了 ModelAndView 对象,进行返回 if (exMv != null) { // ModelAndView 对象为空,则返回 null if (exMv.isEmpty()) { request.setAttribute(EXCEPTION_ATTRIBUTE, ex); returnnull; } // We might still need view name translation for a plain error model... // 没有视图则设置默认视图 if (!exMv.hasView()) { StringdefaultViewName= getDefaultViewName(request); if (defaultViewName != null) { exMv.setViewName(defaultViewName); } } // 打印日志 if (logger.isTraceEnabled()) { logger.trace("Using resolved error view: " + exMv, ex); } elseif (logger.isDebugEnabled()) { logger.debug("Using resolved error view: " + exMv); } // 设置请求中的错误消息属性 WebUtils.exposeErrorRequestAttributes(request, ex, getServletName()); return exMv; } // 未生成 ModelAndView 对象,则抛出异常 throw ex; }