011 异常处理

一 . 概述

  标准的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()方法.

这个方法的核心就是从所有的注册的异常解析器之中获取,然后依次尝试进行处理.

原文地址:https://www.cnblogs.com/trekxu/p/9128954.html