SpringMVC学习记录01——处理流程

###0.前言
《Java EE互联网轻量级框架整合开发——SSM框架(Spring MVC+Spring+MyBatis)和Redis实现》

本文主要记录SpringMVC的处理流程,以便理解SpringMVC框架。

SpringMVC处理流程图

###1.DispactherServlet初始化流程

继承关系(父类->子类):HttpServlet -> HttpServletBean -> FramenworkServlet -> DispactherServlet

  • HttpServlet:Web容器提供的抽象类,可载入Web容器中
  • HttpServletBean:SpringMVC框架提供
  • FramenworkServlet:SpringMVC框架提供,初始化Spring Web Ioc容器
  • DispactherServlet:SpringMVC框架提供,初始化核心组件

DispactherServlet的初始化流程:

  1. HttpServletBean:init() -> initServletBean()(空方法,子类覆写);
  2. FramenworkServlet:initServletBean() -> initWebApplicationContext() -> onRefresh(context)(空方法,子类覆写)
  3. DispactherServlet:onRefresh(context) -> initStrategies(context)

组件的初始化:

//DispatcherServlet类
/**
 * Initialize the strategy objects that this servlet uses.
 * <p>May be overridden in subclasses in order to initialize further strategy objects.
 */
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}
  • MultipartResolver:文件解析器,用于支持服务器文件上传
  • LocaleResolver:国际化解析器,提供国际化支持
  • ThemeResolver:主题解析器,提供主题切换功能
  • HandlerMapping:处理器映射器,存放用户提供的处理器(handler)和对应的多个拦截器(HandlerInterceptor)
  • HandlerAdapter:处理器适配器,用于适配和执行处理器的方法。
    • SimpleControllerHandlerAdapter:控制器适配器(Controller接口)
    • HttpRequestHandlerAdapter:普通请求适配器(HttpRequestHandler接口)
  • HandlerExceptionResolver:处理器异常解析器,对处理器发生的异常进行处理(指定跳异常页等)
  • RequestToViewNameTranslator:视图逻辑名称转换器,将视图名称转化为实际的视图
  • ViewResolver:视图解析器,把逻辑视图解析为实际视图
  • FlashMapManager:Flash开发管理器

###2.DispactherServlet的执行流程

  1. FrameworkServlet: processRequest(request, response) -> doService(request, response)(抽象方法,具体实现由子类完成)publishRequestHandledEvent(...)(处理完成,响应用户)
  2. DispactherServlet:doService(request, response)->doDispatch(request, response)(分派各个组件)

doDispatch的代码:

//DispatcherServlet类
/**
 * Process the actual dispatching to the handler.
 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
 * to find the first that supports the handler class.
 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
 * themselves to decide which methods are acceptable.
 * @param request current HTTP request
 * @param response current HTTP response
 * @throws Exception in case of any kind of processing failure
 */
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); //1.多部分请求实体检测,多文件上传
            multipartRequestParsed = (processedRequest != request);

            // Determine handler for the current request.
            mappedHandler = getHandler(processedRequest); //2. 获取处理器,返回HandlerExecutionChain
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
                noHandlerFound(processedRequest, response);
                return;
            }


            //3.根据handler获取合适的适配器
            // Determine handler adapter for the current request.
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // Process last-modified header, if supported by the handler.
            String method = request.getMethod();
            boolean isGet = "GET".equals(method);
            if (isGet || "HEAD".equals(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (logger.isDebugEnabled()) {
                    logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                }
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

            //额外处理1. 处理拦截器,实际调用interceptor.preHandle(...),异常直接triggerAfterCompletion(...)结束
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            //4.通过处理器适配器执行处理器方法,返回逻辑视图(ModelAndView)
            // Actually invoke the handler.
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            //5.设置ModelAndView对应的viewName,使用ViewNameTranslator
            applyDefaultViewName(processedRequest, mv);

            //额外处理2. 处理拦截器,实际调用interceptor.postHandle(...)
            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.渲染视图->render(...)->view.render(mv.getModelInternal(), request, response);
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    catch (Exception ex) {
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
    catch (Throwable err) {
        triggerAfterCompletion(processedRequest, response, mappedHandler,
                new NestedServletException("Handler processing failed", err));
    }
    finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            // Instead of postHandle and afterCompletion
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        }
        else {
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }
}

通过源码可以知道,在获取请求(Request)后,最终是由DispatcherServletdoDispatch方法进行处理。而doDispatch方法将请求(Request)根据流程分派给各个组件处理,最终返回响应实体(Response)到父类FrameworkServletpublishRequestHandledEvent(...)处理。

doDispatch的步骤:

  1. processRequest处理请求(FrameworkServlet)
  2. 多部分请求实体检测,多文件上传
  3. 获取处理器,返回HandlerExecutionChain(包含一个Handler和多个拦截器interceptor)
  4. 根据handler获取合适的适配器(handler可能是Controller)
  5. 通过处理器适配器执行处理器方法,返回逻辑视图(ModelAndView)
  6. 渲染视图->render(…)->view.render(mv.getModelInternal(), request, response)
  7. publishRequestHandledEvent处理Response,响应用户(FrameworkServlet)

###3.总结
SpringMVC的核心功能主要体现在DispactherServlet类中,由DispactherServlet分派任务给各个组件。而作为开发者,需要完成的便是这些组件的配置,和执行器Handler(Controller)以及拦截器interceptor的编写。

END

– Nowy

– 2018.12.19

分享到