SpringMVC源码解析从service到doDispatch(上))

简介: SpringMVC源码解析从service到doDispatch(上))

请求在被Servlet处理之前会先被过滤器处理,之后调用Servlet的service方法来对相应的请求进行处理响应。所以我们这里分析的入口是Servlet的service方法。

我们在用SpringMVC的时候,通常都会在web.xml中进行这样的配置:

<servlet>
  <servlet-name>spring-mvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:learn-spring-mvc.xml</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>spring-mvc</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

所有的请求(除静态资源)将由DispatcherServlet处理。

image.png

DispatcherServlet继承了FrameworkServlet,FrameworkServlet继承了HttpServletBean,HttpServletBean继承了HttpServlet,HttpServlet继承了GenericServlet,GenericServlet则实现了我们最顶级的接口Servlet和ServletConfig。

  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 {
      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);
        }
      }
    }
  }

从DispatcherServlet的源码中我们没有找到service(ServletRequest req, ServletResponse res)这个方法,但是我们在DispatcherServlet的父类HttpServlet中找到了这个方法,我们去HttpServlet中看看这个方法的内容:


HttpServlet#service

image.png

将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse


因为web开发,用HTTP协议,所以需要HttpServletRequest和HttpServletResponse


接下来就是调用service(HttpServletRequest request, HttpServletResponse response),


HttpServlet和FrameworkServlet中都找到了这个方法,但是HttpServlet是FrameworkServlet的父类,即FrameworkServlet中重写了service这个方法,所以我们这里取FrameworkServlet中去看看这个方法的内容:

FrameworkServlet#service

image.png

根据请求的方法类型转换对应的枚举类


HttpMethod这个定义了这样的几种枚举类型:GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;而这些也是RFC标准中几种请求类型。如果请求类型为PATCH或者没有找到相应的请求类型的话,则直接调用processRequest这个方法。但是这种情况我们很少很少会遇到。

所以这里会执行super.service这个方法。即调用HttpServlet中的service方法。我们看一下HttpServlet中这个service方法的内容:


目录
相关文章
|
3天前
|
canal 缓存 关系型数据库
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
|
3天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
11天前
yolo-world 源码解析(六)(2)
yolo-world 源码解析(六)
23 0
|
11天前
yolo-world 源码解析(六)(1)
yolo-world 源码解析(六)
18 0
|
12天前
yolo-world 源码解析(五)(4)
yolo-world 源码解析(五)
23 0
|
12天前
yolo-world 源码解析(五)(1)
yolo-world 源码解析(五)
34 0
|
26天前
|
XML Java Android开发
Android实现自定义进度条(源码+解析)
Android实现自定义进度条(源码+解析)
53 1
|
12天前
yolo-world 源码解析(二)(2)
yolo-world 源码解析(二)
23 0
|
12天前
Marker 源码解析(二)(3)
Marker 源码解析(二)
17 0

推荐镜像

更多