SpringMVC detailed execution process

1. When the browser initiates a request, it first looks up the IP address corresponding to the domain name according to the DNS, and first judges whether there is a mapping relationship in the browser cache. If there is no local host file, then query the remote domain name resolver

2. After finding the ip, according to the ip logic and the subnet mask, get which network the target machine belongs to, and then use the subnet mask to invert and put the ip address to get the specific host

3. After finding the host, find the corresponding server according to the port number.


4. The request is first intercepted by dispatchServlet, and the URI is extracted from the URL.

5. Then call handlerMapping, query the corresponding request processor according to the URI, and return the handler and interceptor

6. Then query the handlerAdapter according to the request processor, perform data verification and conversion, and then call the handler to trigger pre-interception

7. After calling the handler, modelAndView is returned, and then the view parser separates the model and view for page rendering.

Source DispatcherServlet#doDispatch

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 {
          // 校验是否为上传请求 是上传请求执行解析 否则返回request
         processedRequest = checkMultipart(request);
         multipartRequestParsed = (processedRequest != request);

         // 根据访问的Handler 返回指定对应的HandlerExecutionChain对象 这里从HandlerMapping 集合中查找 HandlerExecutionChain 对象包含Handler与拦截器HandlerInterceptor列表
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null) {
            noHandlerFound(processedRequest, response);
            return;
         }

         // 根据得到的Handler 获取对应的HandlerAdaptor对象
         HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

         // 处理GET、HEAD请求的Last-Modified
         String method = request.getMethod();
         boolean isGet = "GET".equals(method);
         if (isGet || "HEAD".equals(method)) {
            long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
            //当数据没有更改时,就直接返回上次的数据,提高效率
             if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
               return;
            }
         }

         //执行Interceptor的preHandle 
         if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
         }

         // 执行Handler 返回ModelAndView
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

          //如果需要异步处理,直接返回
         if (asyncManager.isConcurrentHandlingStarted()) {
            return;
         }

         //当view为空时,根据request设置默认view,如Handler返回值为void
         applyDefaultViewName(processedRequest, mv);
         //执行相应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);
      }
       //处理返回结果,包括处理异常、渲染页面,发出完成通知触发Interceptor的afterCompletion
      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);
         }
      }
   }
}

Guess you like

Origin blog.csdn.net/qq_29857681/article/details/125617092