【SpringMVC】之源码分析工作流程

一、概述

学习之后,记下笔记,理清思路。

带着问题去思考:

springMVC接收到用户请求之后,如何工作?

springMVC核心组件有哪些?

哪些是程序员需要编写的部分?

二、SpringMVC工作流程

 

 工作流程:

  1. 用户发送请求;
  2. DispatcherSerlvet(前端控制器) 接收请求,调用HandlerMapping;
  3. HandlerMapping(处理器映射器) 去查找处理器Handler(就是Controller),HandlerMapping 返回执行链HandlerExecutionChain(包括Handler对象、拦截器数组)给DispatcherSerlvet;
  4. DispatcherSerlvet调用HandlerAdapter(处理器适配器);
  5. HandlerAdapter去执行Handler;
  6. Handler返回ModelAndView给HandlerAdapter;
  7. HandlerAdapter返回ModelAndView给DispatcherSerlvet;
  8. DispatcherSerlvet调用ViewResolver(视图解析器)进行视图解析;
  9. ViewResolver返回视图对象;
  10. DispatcherSerlvet进行视图渲染
  11. 返回渲染后对象;
  12. 响应请求。

 三、核心组件

  • 前端控制器DispatcherSerlvet

  控制中心,接收请求,转发请求,响应请求

  • 处理器映射器   HandlerMapping

  查找处理器Handler

  • 处理器适配器  HandlerAdapter

  执行处理器Handler

  • 视图解析器  ViewResolver

  解析ModelAndView

  • 处理器Handler    (需要工程师开发)

  Controller

  • 视图View    (需要工程师开发jsp...)

  前端页面

四、源码分析

  1、IDEA创建SpringMVC项目

  参考:https://www.cnblogs.com/chenlinghong/p/8339555.html

  创建出现的问题:

1

web.xml中出现“element servlet-name is not allow here”,

导致系统启动失败

 修改schema,把原来的替换成
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
2  报错:org.apache.catalina.core.StandardContext.listenerStart Error configuring application listener of class org.springframework.web.context.ContextLoaderListener  参考:https://www.cnblogs.com/feiyujun/p/6537510.html

  创建一个简单的SpringMVC项目,只关注SpringMVC的工作流程。

  2、简单写个接口

@Controller
@RequestMapping("/mvc")
public class HelloWorldController {

    @RequestMapping("helloWorld")
    public String hello(){
        return "helloWorld";
    }
}

  3、分析DispatcherServlet

思路:DispatcherServlet继承FrameworkServlet,就是servlet,

  servlet分:初始化,处理方法,销毁方法

  核心就是service,

  (下图是FrameworkServlet中的service方法)

  再看关键的processRequest方法

 

点进去一看,是个抽象方法

那DispatcherServlet肯定重写了该方法

//DispatcherServlet.java
protected
void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if(this.logger.isDebugEnabled()) { String attributesSnapshot = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":""; this.logger.debug("DispatcherServlet with name \'" + this.getServletName() + "\'" + attributesSnapshot + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } HashMap attributesSnapshot1 = null; if(WebUtils.isIncludeRequest(request)) { attributesSnapshot1 = new HashMap(); Enumeration inputFlashMap = request.getAttributeNames(); label108: while(true) { String attrName; do { if(!inputFlashMap.hasMoreElements()) { break label108; } attrName = (String)inputFlashMap.nextElement(); } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); attributesSnapshot1.put(attrName, request.getAttribute(attrName)); } } request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource()); FlashMap inputFlashMap1 = this.flashMapManager.retrieveAndUpdate(request, response); if(inputFlashMap1 != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap1)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try { this.doDispatch(request, response); //关键方法 } finally { if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot1 != null) { this.restoreAttributesAfterInclude(request, attributesSnapshot1); } } }

再看doDispatch,做了啥,看见了关键词getHandler、getHandlerAdapter

getHandler,返回  HandlerExecutionChain

getHandlerAdapter,返回  HandlerAdapter

 

  4、调用getHandler,获取HandlerExecutionChain

 在上面的两个方法上打断点,

this.handlerMappings  有三个元素

this.handlerMappings有三种类型,根据request请求使用不同的HandlerMapping

  1. RequestMappingHandlerMapping (支持带@RequestMapping注释的方法)

  2. BeanNameUrlHandlerMapping

  3. SimpleUrlHandlerMapping (维护URI路径模式到处理程序的显式注册)。

返回handler(一个HandlerExecutionChain对象,包含了处理器controller和一个或多个拦截器),对应DispatcherServlet中的mappedHandler

  4、调用getHandlerAdapter,获取HandlerAdapter

 

 

this.handlerAdapters有三种

  1. HttpRequestHandlerAdapter
  2. SimpleControllerHandlerAdapter
  3. RequestMappingHandlerAdapter

遍历所有类型,判断是否支持当前处理器handler

匹配RequestMappingHandlerAdapter,返回

 

进行到这一步,真正执行我们编写的处理器(Controller)

 

返回ModelAndView

 后面还有视图解析。

 

posted @ 2019-05-26 21:04  tingtingzhou  阅读(338)  评论(0编辑  收藏  举报