Spring源码分析-SpringMVC核心功能DispatcherServlet

SpringMVC的核心功能是DispatcherServlet

 
执行步骤:
(1)用户发送请求至前端控制器DispatcherServlet(调用doDispatch方法);
(2)DispatcherServlet 通过 HandlerMapping 找到与Request请求URL相匹配的HandlerExecutionChain,并返回给DispatcherServlet(HandlerExecutionChain封装了Handler对象);
(3)DispatcherServlet 通过 handler 找到相应的 HandlerAdapter 处理器适配器,并返回给DispatcherServlet;
(4)DispatcherServlet 通过 HandlerAdapter 调用具体处理器,即执行Controller 中相应的处理方法,并返回ModelAndView给DispatcherServlet(ModelAndView:Model用于视图渲染,View用于视图解析) ;
(5)DispatcherServlet 通过 ViewResolver 找到与viewName匹配的 View,并返回给DispatcherServlet(视图解析);
(6)DispatcherServlet 通过 View 将Model数据进行内容填充,生成新的结果页面 View(视图渲染);
(7)DispatcherServlet 将结果页面返回给用户(返回响应)。

1.用户发送请求,执行DispatchServlet 中的doService方法

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                // 2.去HandlerMapping中拿到 handler
                mappedHandler = getHandler(processedRequest);
                // 如果HandlerMapping没有这个请求映射,则直接返回。如静态资源的拦截
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // 3.通过handler来拿到HandlerAdapter
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
                
                // 省略部分代码
                
                // 4.通过 HandlerAdapter 来调用控制器Controller中的方法,返回ModelAndView
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                applyDefaultViewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
            // 处理转发结果,包括出现异常时异常视图的解析及渲染
            // 5.视图解析,通过 ViewResolver 返回View对象
            // 6.视图渲染,通过 view.render 方法将Model渲染成视图
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        // 省略部分代码
    }

2.映射处理器,去HandlerMapping中拿到 handler

这一步是执行 mappedHandler = getHandler(processedRequest); 

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 这里的handlerMappings 在执行 initStrategies()方法时已经初始化
    for (HandlerMapping hm : this.handlerMappings) {
        // 
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}

3.处理适配器,通过handler来拿到HandlerAdapter

这一步执行的是 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    // 这里的handlerMappings 在执行 initStrategies()方法时已经初始化
    for (HandlerAdapter ha : this.handlerAdapters) {
        // 
        if (ha.supports(handler)) {
            return ha;
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
                               "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

4.调用处理器相应功能方法,通过 HandlerAdapter 来调用控制器Controller中的方法,返回ModelAndView

这里执行的是 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

@Override
protected ModelAndView handleInternal(HttpServletRequest request,
                                      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    ModelAndView mav;
    checkRequest(request);
    // 省略部分代码...
    // Execute invokeHandlerMethod in synchronized block if required.
    if (this.synchronizeOnSession) {
        // 
    } else {
        // 代码关键部分
        mav = invokeHandlerMethod(request, response, handlerMethod);
    }
    // 省略部分代码...

    return mav;
}


protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
                                           HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
        // 省略部分代码...

        // 代码关键部分:方法调用,执行Controller 中的方法
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        if (asyncManager.isConcurrentHandlingStarted()) {
            return null;
        }
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    finally {
        webRequest.requestCompleted();
    }
}

 下面这个方法就是 视图解析 + 视图渲染

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

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);
        }
    }
    else {
        if (logger.isDebugEnabled()) {
            logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
                         "': assuming HandlerAdapter completed request handling");
        }
    }
    // 省略部分代码...
}

5.视图解析,通过 ViewResolver 返回View对象

这一步执行的是 view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); 

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // Determine locale for request and apply it to the response.
    Locale locale = this.localeResolver.resolveLocale(request);
    response.setLocale(locale);

    View view;
    if (mv.isReference()) {
        // 代码关键部分:通过 ViewResolver 返回View对象
        view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
                                       "' in servlet with name '" + getServletName() + "'");
        }
    }
    else {
        // No need to lookup: the ModelAndView object contains the actual View object.
        view = mv.getView();
        if (view == null) {
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
                                       "View object in servlet with name '" + getServletName() + "'");
        }
    }
    // 省略部分代码...
}
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
                               HttpServletRequest request) throws Exception {

    for (ViewResolver viewResolver : this.viewResolvers) {
        View view = viewResolver.resolveViewName(viewName, locale);
        if (view != null) {
            return view;
        }
    }
    return null;
}

6.视图渲染,通过 view.render 方法将Model渲染成视图

这一步调用的是 view.render(mv.getModelInternal(), request, response);

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // Determine locale for request and apply it to the response.
    Locale locale = this.localeResolver.resolveLocale(request);
    response.setLocale(locale);

    View view;
    // 省略部分代码...
    try {
        if (mv.getStatus() != null) {
            response.setStatus(mv.getStatus().value());
        }
        // 通过 view.render 方法将Model渲染成视图,及将新的视图返回给页面
        view.render(mv.getModelInternal(), request, response);
    } catch (Exception ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
                         getServletName() + "'", ex);
        }
        throw ex;
    }
}
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    if (logger.isTraceEnabled()) {
        logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
                     " and static attributes " + this.staticAttributes);
    }

    Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
    prepareResponse(request, response);
    // 将Model渲染成新的视图并响应请求
    renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
原文地址:https://www.cnblogs.com/caoxb/p/12379977.html