SpringMVC执行流程

DispatcherServlet的初始化过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • org.springframework.web.servlet.FrameworkServlet#initServletBean
protected final void initServletBean() throws ServletException {
	//...
    try {
        this.webApplicationContext = this.initWebApplicationContext();
        this.initFrameworkServlet();
    } catch (RuntimeException | ServletException var4) {
        this.logger.error("Context initialization failed", var4);
        throw var4;
    }
    //...
}
  • org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext
    初始化SpringMVC的IoC容器。
protected WebApplicationContext initWebApplicationContext() {
    WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
    WebApplicationContext wac = null;
	//...
    if (wac == null) {
    	//初始化WebApplicationContext(IoC容器)
        wac = this.createWebApplicationContext(rootContext);
    }

    if (!this.refreshEventReceived) {
        synchronized(this.onRefreshMonitor) {
        	//刷新WebApplicationContext(IoC容器)
            this.onRefresh(wac);
        }
    }

    if (this.publishContext) {
    	//在应用域内共享WebApplicationContext(IoC容器)
        String attrName = this.getServletContextAttributeName();
        this.getServletContext().setAttribute(attrName, wac);
    }

    return wac;
}
  • org.springframework.web.servlet.FrameworkServlet#createWebApplicationContext(org.springframework.context.ApplicationContext)
    创建SpringMVC的IoC容器。
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
    Class<?> contextClass = this.getContextClass();
    if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
        throw new ApplicationContextException("Fatal initialization error in servlet with name '" + this.getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
    } else {
    	//创建IoC容器
        ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
        wac.setEnvironment(this.getEnvironment());
        //设置父容器(将Spring的IoC容器设置为SpringMVC的IoC容器的父容器)
        wac.setParent(parent);
        String configLocation = this.getContextConfigLocation();
        if (configLocation != null) {
            wac.setConfigLocation(configLocation);
        }

        this.configureAndRefreshWebApplicationContext(wac);
        return wac;
    }
}
  • org.springframework.web.servlet.DispatcherServlet#onRefresh
    刷新SpringMVC的IoC容器。
protected void onRefresh(ApplicationContext context) {
    this.initStrategies(context);
}
  • org.springframework.web.servlet.DispatcherServlet#initStrategies
    初始化策略,即初始化DispatcherServlet的各个组件。
protected void initStrategies(ApplicationContext context) {
    this.initMultipartResolver(context);
    this.initLocaleResolver(context);
    this.initThemeResolver(context);
    this.initHandlerMappings(context);
    this.initHandlerAdapters(context);
    this.initHandlerExceptionResolvers(context);
    this.initRequestToViewNameTranslator(context);
    this.initViewResolvers(context);
    this.initFlashMapManager(context);
}
DispatcherServlet的服务过程

在这里插入图片描述

  • javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;
        this.service(request, response);
    } else {
        throw new ServletException("non-HTTP request or response");
    }
}
  • javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     String method = req.getMethod();
     long lastModified;
     if (method.equals("GET")) {
         lastModified = this.getLastModified(req);
         if (lastModified == -1L) {
             this.doGet(req, resp);
         } else {
             long ifModifiedSince = req.getDateHeader("If-Modified-Since");
             if (ifModifiedSince < lastModified) {
                 this.maybeSetLastModified(resp, lastModified);
                 this.doGet(req, resp);
             } else {
                 resp.setStatus(304);
             }
         }
     } else if (method.equals("HEAD")) {
         lastModified = this.getLastModified(req);
         this.maybeSetLastModified(resp, lastModified);
         this.doHead(req, resp);
     } else if (method.equals("POST")) {
         this.doPost(req, resp);
     } else if (method.equals("PUT")) {
         this.doPut(req, resp);
     } else if (method.equals("DELETE")) {
         this.doDelete(req, resp);
     } else if (method.equals("OPTIONS")) {
         this.doOptions(req, resp);
     } else if (method.equals("TRACE")) {
         this.doTrace(req, resp);
     } else {
         String errMsg = lStrings.getString("http.method_not_implemented");
         Object[] errArgs = new Object[]{method};
         errMsg = MessageFormat.format(errMsg, errArgs);
         resp.sendError(501, errMsg);
     }

 }
  • org.springframework.web.servlet.FrameworkServlet#service
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
        super.service(request, response);
    } else {
        this.processRequest(request, response);
    }
}

protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}

protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}

protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}

protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}

protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    if (this.dispatchOptionsRequest || CorsUtils.isPreFlightRequest(request)) {
        this.processRequest(request, response);
        if (response.containsHeader("Allow")) {
            return;
        }
    }

    super.doOptions(request, new HttpServletResponseWrapper(response) {
        public void setHeader(String name, String value) {
            if ("Allow".equals(name)) {
                value = (StringUtils.hasLength(value) ? value + ", " : "") + HttpMethod.PATCH.name();
            }

            super.setHeader(name, value);
        }
    });
}
  • org.springframework.web.servlet.FrameworkServlet#processRequest
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	//...
    try {
        this.doService(request, response);
    } catch (IOException | ServletException var16) {
        failureCause = var16;
        throw var16;
    } catch (Throwable var17) {
        failureCause = var17;
        throw new NestedServletException("Request processing failed", var17);
    } finally {
        this.resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }

        this.logResult(request, response, (Throwable)failureCause, asyncManager);
        this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
    }

}
  • org.springframework.web.servlet.DispatcherServlet#doService
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	//...
    try {
        this.doDispatch(request, response);
    } finally {
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
            this.restoreAttributesAfterInclude(request, attributesSnapshot);
        }

        if (this.parseRequestPath) {
            ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
        }

    }
}
  • org.springframework.web.servlet.DispatcherServlet#doDispatch
    • mappedHandler.applyPreHandle(processedRequest, response)
    • mv = ha.handle(processedRequest, response, mappedHandler.getHandler())
    • mappedHandler.applyPostHandle(processedRequest, response, mv)
    • this.processDispatchResult()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   HttpServletRequest processedRequest = request;
   HandlerExecutionChain mappedHandler = null;
   boolean multipartRequestParsed = false;
   WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

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

           try {
               processedRequest = this.checkMultipart(request);
               multipartRequestParsed = processedRequest != request;
               mappedHandler = this.getHandler(processedRequest);
				//...
               HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
				//...
               if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                   return;
               }

               mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				//...
               mappedHandler.applyPostHandle(processedRequest, response, mv);
           } catch (Exception var20) {
               dispatchException = var20;
           } catch (Throwable var21) {
               dispatchException = new NestedServletException("Handler dispatch failed", var21);
           }

           this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
       } catch (Exception var22) {
           this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
       } catch (Throwable var23) {
           this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
       }

   } finally {
       if (asyncManager.isConcurrentHandlingStarted()) {
           if (mappedHandler != null) {
               mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
           }
       } else if (multipartRequestParsed) {
           this.cleanupMultipart(processedRequest);
       }

   }
}
  • org.springframework.web.servlet.DispatcherServlet#processDispatchResult
    • this.render(mv, request, response)
    • mappedHandler.triggerAfterCompletion(request, response, (Exception)null)
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
	//...

   if (mv != null && !mv.wasCleared()) {
       this.render(mv, request, response);
		//...
   } else if (this.logger.isTraceEnabled()) {
       this.logger.trace("No view rendering, null ModelAndView returned.");
   }

   if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
       if (mappedHandler != null) {
           mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
       }

   }
}
SpringMVC的执行流程
  1. 用户向服务器发送请求,请求被SpringMVC前端控制器DispatcherServlet捕获。
  2. DispatcherServlet对请求URL进行解析,得到请求资源标识符URI,判断请求URI对应的映射。
    如果该URI不存在,则判断是否启用了DefaultServlet。
    如果没有启用DefaultServlet,则直接报404。
    如果启用了DefaultServlet,且找到了该URI,则返回对应的静态资源。
    如果启用了DefaultServlet,但仍找不到该URI,则报404。
  3. 如果URI存在,会根据该URI,调用HandlerMapping获得该Handler(或Controller)配置的所有相关对象,包括Handler对象及Handler对象对应的拦截器,最后以HandlerExecutionChain执行链对象的形式返回。
  4. DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。
  5. 如果成功获得HandlerAdapter,此时将开始执行拦截器的perHandler。
  6. 提取Request中的模型数据,填充Handler入参,开始执行Handler(或Controller)方法,处理请求。在填充Handler入参的过程中,根据配置,Spring会完成一些额外工作,如:
    1)HttpMessageConveter:将请求消息(如json、xml等数据)转换成一个对象,将对象转换成指定的响应信息。
    2)数据转换:对请求消息进行数据转换,如String换成Integer、Double等。
    3)数据格式化:对请求消息进行格式化,如将字符串转换成格式化数字或格式化日期等。
    4)数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或者Error中。
  7. Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象。
  8. 控制器方法执行完后,开始执行拦截器的postHandler方法。
  9. 根据控制器方法返回的ModelAndView选择一个合适的ViewResolver进行视图解析,根据Model和View来渲染视图。
  10. 渲染视图完毕后执行拦截器的afterCompletion方法。
  11. 将渲染结果返回给客户端。

SpringMVC是跟着杨博超老师学的,给这位老师点赞。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值