美文网首页
SpringMVC运行流程

SpringMVC运行流程

作者: 会忆 | 来源:发表于2018-06-20 15:51 被阅读0次
    SpringMVC运行时序图,来源网络

    1、DispatcherServlet 获取请求,设置请求属性

    2、执行doDispatcher()方法

    3、根据请求返回一个含有Handler 的 HandlerExecutionChain (处理器执行链)对象

    4、根据Handler 选择匹配的HandlerAdapter(处理器适配器)

    5、HandlerAdapter 调用 Handler处理请求,返回ModleAndView 对象

    6、渲染视图,响应请求

    本文源码为Springmvc - 4.3.18,如有错误请多多指教!

    1、DispatcherServlet.doServer(),设置请求属性

    /**
     * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
     * for the actual dispatching.
     */
    @Override
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
       if (logger.isDebugEnabled()) {
          String resumed = WebAsyncUtils.getAsyncManager(request)
                                      .hasConcurrentResult() ? " resumed" : "";
          logger.debug("DispatcherServlet with name '" + getServletName() 
                       + "'" + resumed + " processing " + request.getMethod() 
                       + " request for [" + getRequestUri(request) + "]");
       }
    
       // Keep a snapshot of the request attributes in case of an include,
       // to be able to restore the original attributes after the include.
       Map<String, Object> attributesSnapshot = null;
       if (WebUtils.isIncludeRequest(request)) {
          attributesSnapshot = new HashMap<String, Object>();
          Enumeration<?> attrNames = request.getAttributeNames();
          while (attrNames.hasMoreElements()) {
             String attrName = (String) attrNames.nextElement();
             if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
             }
          }
       }
    
       // Make framework objects available to handlers and view objects.
       request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
       request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
       request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
       request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
    
       FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
       if (inputFlashMap != null) {
          request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
       }
       request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
       request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    
       try {
           //2、执行委派
          doDispatch(request, response);
       }
       finally {
          if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
             // Restore the original attribute snapshot, in case of an include.
             if (attributesSnapshot != null) {
                restoreAttributesAfterInclude(request, attributesSnapshot);
             }
          }
       }
    }
    

    2、DispatcherServlet.doDispatch(),执行具体的方法

    /**
     * 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);
             multipartRequestParsed = (processedRequest != request);
    
             // Determine handler for the current request.
             // 3 为当前请求寻找handler;返回HandlerExecutionChain对象
             mappedHandler = getHandler(processedRequest);
             if (mappedHandler == null || mappedHandler.getHandler() == null) {
                noHandlerFound(processedRequest, response);
                return;
             }
    
             // Determine handler adapter for the current request.
             // 4 为handler寻找handleradapter适配器,返回HandlerAdapter
             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;
                }
             }
    
             if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
             }
    
             // Actually invoke the handler.
             // 5 HandlerAdapter调用handler处理请求,并返回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);
          }
           // 6 渲染视图
          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);
             }
          }
       }
    }
    

    3、为当前请求寻找handler;返回HandlerExecutionChain对象(含有handler和interceptors)

    • DispatcherServlet.getHandler(HttpServletRequest request)
    /**
     * Return the HandlerExecutionChain for this request.
     * <p>Tries all handler mappings in order.
     * @param request current HTTP request
     * @return the HandlerExecutionChain, or {@code null} if no handler could be found
     */
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
       for (HandlerMapping hm : this.handlerMappings) {
          if (logger.isTraceEnabled()) {
             logger.trace(
                   "Testing handler map [" + hm + "] in DispatcherServlet with name '" 
                   + getServletName() + "'");
          }
          // 3.1 获取HandlerExecutionChain对象
          HandlerExecutionChain handler = hm.getHandler(request);
          if (handler != null) {
             return handler;
          }
       }
       return null;
    }
    

    3.1 获取HandlerExecutionChain对象

    • AbstractHandlerMapping.getHandler(HttpServletRequest request)
    /**
     * 如果没有找到Hander,则返回默认的
     * Look up a handler for the given request, falling back to the default
     * handler if no specific one is found.
     * @param request current HTTP request
     * @return the corresponding handler instance, or the default handler
     * @see #getHandlerInternal
     */
    @Override
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
      // 3.1.1 根据请求寻找handler
      Object handler = getHandlerInternal(request);
       if (handler == null) {
          handler = getDefaultHandler();
       }
       if (handler == null) {
          return null;
       }
       // Bean name or resolved handler?
       if (handler instanceof String) {
          String handlerName = (String) handler;
          handler = getApplicationContext().getBean(handlerName);
       }
       // 3.1.2 构建一个hHandlerExecutionChain(含有handler和interceptors)
       HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
       if (CorsUtils.isCorsRequest(request)) {
          CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
          CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
          CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
          executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
       }
       return executionChain;
    }
    

    3.1.1 根据请求寻找handler

    • AbstractHandlerMethodMapping<T>.getHandlerInternal(HttpServletRequest request)
    /**
     * Look up a handler method for the given request.
     */
    @Override
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
       //请求地址
       String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
       if (logger.isDebugEnabled()) {
          logger.debug("Looking up handler method for path " + lookupPath);
       }
       this.mappingRegistry.acquireReadLock();
       try {
          HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
          if (logger.isDebugEnabled()) {
             if (handlerMethod != null) {
                logger.debug("Returning handler method [" + handlerMethod + "]");
             }
             else {
                logger.debug("Did not find handler method for [" + lookupPath + "]");
             }
          }
          return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
       }
       finally {
          this.mappingRegistry.releaseReadLock();
       }
    }
    

    3.1.2 构建一个hHandlerExecutionChain(含有handler和interceptors)

    • AbstractHandlerMapping.getHandlerExecutionChain(Object handler, HttpServletRequest request)
    /**
     * Build a {@link HandlerExecutionChain} for the given handler, including
     * applicable interceptors.
     * <p>The default implementation builds a standard {@link HandlerExecutionChain}
     * with the given handler, the handler mapping's common interceptors, and any
     * {@link MappedInterceptor}s matching to the current request URL. Interceptors
     * are added in the order they were registered. Subclasses may override this
     * in order to extend/rearrange the list of interceptors.
     * <p><b>NOTE:</b> The passed-in handler object may be a raw handler or a
     * pre-built {@link HandlerExecutionChain}. This method should handle those
     * two cases explicitly, either building a new {@link HandlerExecutionChain}
     * or extending the existing chain.
     * <p>For simply adding an interceptor in a custom subclass, consider calling
     * {@code super.getHandlerExecutionChain(handler, request)} and invoking
     * {@link HandlerExecutionChain#addInterceptor} on the returned chain object.
     * @param handler the resolved handler instance (never {@code null})
     * @param request current HTTP request
     * @return the HandlerExecutionChain (never {@code null})
     * @see #getAdaptedInterceptors()
     */
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
       HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
             (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    
       String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
        //遍历可用的拦截器
       for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
          if (interceptor instanceof MappedInterceptor) {
             MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
             if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
             }
          }
          else {
             chain.addInterceptor(interceptor);
          }
       }
       return chain;
    }
    

    4、 为Handler寻找HandlerAdapter适配器,返回HandlerAdapter

    • DispatcherServlet.getHandlerAdapter(Object handler)
    /**
     * Return the HandlerAdapter for this handler object.
     * @param handler the handler object to find an adapter for
     * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
     */
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
       for (HandlerAdapter ha : this.handlerAdapters) {
          if (logger.isTraceEnabled()) {
             logger.trace("Testing handler adapter [" + ha + "]");
          }
           // 4.1是否能处理这个handler
          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.1是否能处理这个handler

    在此处会遍历所有当前存在的适配器,这里拿一个举例

    • HttpRequestHandlerAdapter.supports(Object handler)
    @Override
    public boolean supports(Object handler) {
       return (handler instanceof HttpRequestHandler);
    }
    

    5、HandlerAdapter调用handler处理请求,并返回ModelAndView对象

    • AbstractHandlerMethodAdapter.handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    /**
     * This implementation expects the handler to be an {@link HandlerMethod}.
     */
    @Override
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
          throws Exception {
        //5.1 处理请求
       return handleInternal(request, response, (HandlerMethod) handler);
    }
    

    5.1 处理请求

    • RequestMappingHandlerAdapter.handleInternal(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod)
    @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) {
          HttpSession session = request.getSession(false);
          if (session != null) {
             Object mutex = WebUtils.getSessionMutex(session);
             synchronized (mutex) {
                mav = invokeHandlerMethod(request, response, handlerMethod);
             }
          }
          else {
             // No HttpSession available -> no mutex necessary
             mav = invokeHandlerMethod(request, response, handlerMethod);
          }
       }
       else {
          // No synchronization on session demanded at all...
          // 5.1.1 调用Handler方法
          mav = invokeHandlerMethod(request, response, handlerMethod);
       }
    
       if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
          if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
             applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
          }
          else {
             prepareResponse(response);
          }
       }
    
       return mav;
    }
    

    5.1.1 调用Handler方法

    • RequestMappingHandlerAdapter.invokeHandlerMethod(HttpServletRequest request,

    HttpServletResponse response, HandlerMethod handlerMethod)

    /**
     * Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
     * if view resolution is required.
     * @since 4.2
     * @see #createInvocableHandlerMethod(HandlerMethod)
     */
    protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
          HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
       ServletWebRequest webRequest = new ServletWebRequest(request, response);
       try {
          WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
          ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
    
          ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
          invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
          invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
          invocableMethod.setDataBinderFactory(binderFactory);
          invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
    
          ModelAndViewContainer mavContainer = new ModelAndViewContainer();
          mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
          modelFactory.initModel(webRequest, mavContainer, invocableMethod);
          mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
    
          AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
          asyncWebRequest.setTimeout(this.asyncRequestTimeout);
    
          WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
          asyncManager.setTaskExecutor(this.taskExecutor);
          asyncManager.setAsyncWebRequest(asyncWebRequest);
          asyncManager.registerCallableInterceptors(this.callableInterceptors);
          asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
    
          if (asyncManager.hasConcurrentResult()) {
             Object result = asyncManager.getConcurrentResult();
             mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
             asyncManager.clearConcurrentResult();
             if (logger.isDebugEnabled()) {
                logger.debug("Found concurrent result value [" + result + "]");
             }
             invocableMethod = invocableMethod.wrapConcurrentResult(result);
          }
    
          invocableMethod.invokeAndHandle(webRequest, mavContainer);
          if (asyncManager.isConcurrentHandlingStarted()) {
             return null;
          }
    
          return getModelAndView(mavContainer, modelFactory, webRequest);
       }
       finally {
          webRequest.requestCompleted();
       }
    }
    
    • RequestMappingHandlerAdapter.getModelAndView(ModelAndViewContainer mavContainer,

    ModelFactory modelFactory, NativeWebRequest webRequest)

    private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
          ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
    
       modelFactory.updateModel(webRequest, mavContainer);
       if (mavContainer.isRequestHandled()) {
          return null;
       }
       ModelMap model = mavContainer.getModel();
       ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
       if (!mavContainer.isViewReference()) {
          mav.setView((View) mavContainer.getView());
       }
       if (model instanceof RedirectAttributes) {
          Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
          HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
          RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
       }
       return mav;
    }
    

    6、 渲染视图

    • DispatcherServlet.processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception)
    /**
    * Handle the result of handler selection and handler invocation, which is
    * either a ModelAndView or an Exception to be resolved to a ModelAndView.
    */
    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()) {
            //6.1 渲染视图
            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");
            }
        }
    
        if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            // Concurrent handling started during a forward
            return;
        }
    
        if (mappedHandler != null) {
            mappedHandler.triggerAfterCompletion(request, response, null);
        }
    }
    

    6.1 渲染视图

    • DispatcherServlet.render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
    /**
     * Render the given ModelAndView.
     * <p>This is the last stage in handling a request. It may involve resolving the view by name.
     * @param mv the ModelAndView to render
     * @param request current HTTP servlet request
     * @param response current HTTP servlet response
     * @throws ServletException if view is missing or cannot be resolved
     * @throws Exception if there's a problem rendering the view
     */
    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()) {
          // We need to resolve the view name.
          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() + "'");
          }
       }
    
       // Delegate to the View object for rendering.
       if (logger.isDebugEnabled()) {
          logger.debug("Rendering view [" + view 
                       + "] in DispatcherServlet with name '" 
                       + getServletName() + "'");
       }
       try {
          if (mv.getStatus() != null) {
             response.setStatus(mv.getStatus().value());
          }
          //6.1.1 视图渲染
          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;
       }
    }
    

    6.1.1 视图渲染

    • AbstractView.render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
    /**
     * Prepares the view given the specified model, merging it with static
     * attributes and a RequestContext attribute, if necessary.
     * Delegates to renderMergedOutputModel for the actual rendering.
     * @see #renderMergedOutputModel
     */
    @Override
    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);
       renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
    }
    

    相关文章

      网友评论

          本文标题:SpringMVC运行流程

          本文链接:https://www.haomeiwen.com/subject/tdjxyftx.html