Spring MVC 核心处理流程

本文介绍了Spring MVC框架的基本概念,包括其MVC设计模式、请求驱动类型的特点及简化开发的目标。详细阐述了web.xml配置文件中ContextLoaderListener与DispatcherServlet的作用及初始化过程,并概述了Spring MVC处理请求的具体流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、SpringMVC简介

是一种基于JAVA实现了Web MVC设计模式的请求驱动类型的轻量级Web框架。

解析:

1、MVC架构模式的思想:将Web层进行指责解耦

2、基于请求驱动:请求-相应模型

3、框架的目的:简化开发

二、web.xml配置说明

1、ContextLoaderListener 初始化



从图中我们可以看出ContextLoaderListener 实现了 ServletContextListener 所以在web容器启动时它就进行了配置信息的初始化

在我们的spring xml配置文件文件中 除了用于springmvc那部分,其他的配置都在ContextLoaderListener 中进行初始化


像这些配置文件中我们所配置的相关bean,都会在这一步被初始化到spring的bean工厂


2、DispatcherServlet(分发器) 初始化


从配置中我们可以看出,它就是一个servlert 而且 load-on-startup 为1 所以在web容器启动的时候,它就被进行了初始化,

它初始化的东西就是我们在 springMvc-servlet.xml 中配置的信息。

继承关系:


在web容器启动时将调用HttpServletBean中的init方法,该方法的主要作用是将servlet初始化参数(init-param)设置到该组件上,

而且HttpServletBean还提供给子类一个初始化扩展店,initServletBean(),该方法由FramewordServlet覆盖。

FrameworkServlet继承HttpServletBean 通过initServletBean()进行web上下文初始化,该方法主要覆盖以下两件事情:初始化web     上下文、提供子类初始化扩展点。



[java]  view plain  copy
  1. protected WebApplicationContext initWebApplicationContext() {  
  2.     //ROOT上下文(ContextLoaderListener加载的)  
  3.     WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());  
  4.     WebApplicationContext wac = null;  
  5.     if (this.webApplicationContext != null) {  
  6.         //1、在创建该Servlet注入的上下文  
  7.         wac = this.webApplicationContext;  
  8.         if (wac instanceof ConfigurableWebApplicationContext) {  
  9.             ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;  
  10.             if (!cwac.isActive()) {  
  11.                 if (cwac.getParent() == null) {  
  12.                     cwac.setParent(rootContext);  
  13.                 }  
  14.                 configureAndRefreshWebApplicationContext(cwac);  
  15.             }  
  16.         }  
  17.     }  
  18.     if (wac == null) {  
  19.         //2、查找已经绑定的上下文  
  20.         wac = findWebApplicationContext();  
  21.     }  
  22.     if (wac == null) {  
  23.         //3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListener  
  24.         wac = createWebApplicationContext(rootContext);  
  25.     }  
  26.     if (!this.refreshEventReceived) {  
  27.         onRefresh(wac);//4、刷新上下文(执行一些初始化)  
  28.     }  
  29.     if (this.publishContext) {  
  30.         String attrName = getServletContextAttributeName();  
  31.         getServletContext().setAttribute(attrName, wac);  
  32.         if (this.logger.isDebugEnabled()) {  
  33.             this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +"' as ServletContext attribute with name [" + attrName + "]");  
  34.         }  
  35.     }  
  36.     return wac;  
  37. }  

DispatcherServlet继承FrameworkServlet,并实现了onRefresh()方法提供一些前端控制器相关的配置



从如上代码可以看出,DispatcherServlet启动时会进行我们需要的Web层Bean的配置,如HandlerMapping、HandlerAdapter等,而且如果我们没有     配置,还会给我们提供默认的配置。

默认配置:



3、ContextLoaderListener初始化上下文 和 DispatcherServlet初始化上下文的关系

从图中我们可以看出,ContextLoaderListener 初始化的上下文bean是对整个应用程序共享的,而DispatcherServlet 初始化的

上下文只对Spring Web Mvc有效。

三、SpringMVC处理请求流程

SpringMVC框架是一个基于请求驱动的Web框架,并且使用了‘前端控制器’模型来进行设计,再根据‘请求映射规则’分发给相应的页面控制器进行处理。

具体流程:


1、  首先用户 发送请求—— >DispatcherServlet , 分发器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;

2、  DispatcherServlet —— >HandlerMapping , HandlerMapping 将会把请求映射为 HandlerExecutionChain 对象(包含一个 Handler 处理器(Controller)对象、多个 HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;

3、  DispatcherServlet —— >HandlerAdapter , HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;

4、  HandlerAdapter —— > 处理器功能处理方法的调用, HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理(在调用处理器前会先执行spring的前置拦截器preHandle);并返回一个 ModelAndView 对象(包含模型数据、逻辑视图名),返回视图后会执行spring的后置拦截器postHandle;

5、  ModelAndView 的逻辑视图名—— > ViewResolver , ViewResolver 将把逻辑视图名解析为具体的 View,通过这种策略模式,很容易更换其他视图技术;

6、  View —— > 渲染 ,View 会根据传进来的 Model 模型数据进行渲染,此处的 Model 实际是一个 Map 数据结构,因此很容易支持其他视图技术(这步处理完后执行spring的完成后拦截器)

7、  返回控制权给 DispatcherServlet , 由 DispatcherServlet 返回响应给用户,到此一个流程结束。

DispatcherServlet 的分发控制主要是在doDispatch 中完成,接下来我来看下源码

[java]  view plain  copy
  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.         HttpServletRequest processedRequest = request;  
  3.         HandlerExecutionChain mappedHandler = null;  
  4.         boolean multipartRequestParsed = false;  
  5.   
  6.         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
  7.   
  8.         try {  
  9.             ModelAndView mv = null;  
  10.             Exception dispatchException = null;  
  11.   
  12.             try {  
  13.                 //步骤1、检查请求是否是multipart(如文件上传),如果是将通过MultipartResolver解析    
  14.                 processedRequest = checkMultipart(request);  
  15.                 multipartRequestParsed = (processedRequest != request);  
  16.   
  17.                  //步骤2、请求到处理器(页面控制器Controller)的映射,通过HandlerMapping进行映射   
  18.                 mappedHandler = getHandler(processedRequest, false);  
  19.                 if (mappedHandler == null || mappedHandler.getHandler() == null) {  
  20.                     noHandlerFound(processedRequest, response);  
  21.                     return;  
  22.                 }  
  23.   
  24.                 //步骤3、处理器适配,将我们的处理器包装成相应的适配器(从而支持多种类型的处理器)  
  25.                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
  26.   
  27.                 // Process last-modified header, if supported by the handler.  
  28.                 //304 Not Modified缓存支持    
  29.                 String method = request.getMethod();  
  30.                 boolean isGet = "GET".equals(method);  
  31.                 if (isGet || "HEAD".equals(method)) {  
  32.                     long lastModified = ha.getLastModified(request, mappedHandler.getHandler());  
  33.                     if (logger.isDebugEnabled()) {  
  34.                         logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);  
  35.                     }  
  36.                     if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {  
  37.                         return;  
  38.                     }  
  39.                 }  
  40.                 //执行处理器相关的拦截器的前置理(HandlerInterceptor.preHandle)   
  41.                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {  
  42.                     return;  
  43.                 }  
  44.                 //步骤4、由适配器执行处理器(调用处理器相应功能处理方法)    
  45.                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  46.   
  47.                 if (asyncManager.isConcurrentHandlingStarted()) {  
  48.                     return;  
  49.                 }  
  50.                 applyDefaultViewName(request, mv);  
  51.                 //执行处理器相关的拦截器的后处理(HandlerInterceptor.postHandle)    
  52.                 mappedHandler.applyPostHandle(processedRequest, response, mv);  
  53.             }  
  54.             catch (Exception ex) {  
  55.                 dispatchException = ex;  
  56.             }  
  57.             //这里面执行了处理器相关拦截器的完成后处理(HandlerInterceptor.afterCompletion)  
  58.             processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  
  59.         }  
  60.         catch (Exception ex) {  
  61.             triggerAfterCompletion(processedRequest, response, mappedHandler, ex);  
  62.         }  
  63.         catch (Error err) {  
  64.             triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);  
  65.         }  
  66.         finally {  
  67.             if (asyncManager.isConcurrentHandlingStarted()) {  
  68.                 // Instead of postHandle and afterCompletion  
  69.                 if (mappedHandler != null) {  
  70.                     mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);  
  71.                 }  
  72.             }  
  73.             else {  
  74.                 // Clean up any resources used by a multipart request.  
  75.                 if (multipartRequestParsed) {  
  76.                     cleanupMultipart(processedRequest);  
  77.                 }  
  78.             }  
  79.         }  
  80.     }  
到此我们已经简单的了解了 Spring  MVC 核心的处理流程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值