Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringMVC执行流程和源码分析

SpringMVC执行流程和源码分析

原创
作者头像
在下是首席架构师
发布于 2022-08-01 13:17:15
发布于 2022-08-01 13:17:15
29200
代码可运行
举报
文章被收录于专栏:从入门到出门从入门到出门
运行总次数:0
代码可运行

SpringMVC执行流程:

  1. 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
  2. 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
  3. DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
  4. HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
  5. Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
  6. HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
  7. DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
  8. ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
  9. DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
  10. 视图负责将结果显示到浏览器(客户端)。
代码追踪

请求到达前端控制器的第一站,先做些准备工作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
 * for the actual dispatching.
 */
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   if (logger.isDebugEnabled()) {
      String requestUri = urlPathHelper.getRequestUri(request);
      logger.debug("DispatcherServlet with name '" + getServletName() + "' processing " + request.getMethod() +
            " request for [" + requestUri + "]");
   }

    //保护现场
   // 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)) {
      logger.debug("Taking snapshot of request attributes before include");
      attributesSnapshot = new HashMap<String, Object>();
      Enumeration<?> attrNames = request.getAttributeNames();
      while (attrNames.hasMoreElements()) {
         String attrName = (String) attrNames.nextElement();
         if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
            attributesSnapshot.put(attrName, request.getAttribute(attrName));
         }
      }
   }

    //将框架相关信息存储至request,方便后面的处理器和视图用到
   // 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 {
      //步骤1
      doDispatch(request, response);
   }
   finally {
      // Restore the original attribute snapshot, in case of an include.
      if (attributesSnapshot != null) {
         restoreAttributesAfterInclude(request, attributesSnapshot);
      }
   }
}

开始处理请求

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
		    //步骤2-3
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
		    //步骤4
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = HttpMethod.GET.matches(method);
                    if (isGet || HttpMethod.HEAD.matches(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }

                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
		    //步骤5-9
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }
		//步骤10
                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);
            }

        }
    }
    

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
SpringMVC之请求流程
org.springframework.web.servlet.DispatcherServlet#doService
九转成圣
2024/04/10
1060
SpringMVC之请求流程
SpringMVC:SpringMVC执行流程
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理
愷龍
2023/02/27
6500
SpringMVC:SpringMVC执行流程
SpringMVC DispatcherServlet执行流程及源码分析你要知道的SpringMVC DispatcherServlet执行流程及源码分析都在这里
你要知道的SpringMVC DispatcherServlet执行流程及源码分析都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本系列文章主要根据源码讲解SpringMVC的启动过程,以及相关重要组件的源码分析。阅读此系列文章需要具备Spring以及SpringMVC相关知识。本文将分以下几篇文章进行讲解,读者可按需查阅。 SpringMVC 启动流程及相关源码分析 SpringMVC DispatcherServlet执行流程及
WWWWDotPNG
2018/04/10
2.3K0
SpringMVC DispatcherServlet执行流程及源码分析你要知道的SpringMVC DispatcherServlet执行流程及源码分析都在这里
SpringMVC 源码分析之 DispatcherServlet
松哥原创的 Spring Boot 视频教程已经杀青,感兴趣的小伙伴戳这里-->Spring Boot+Vue+微人事视频教程
江南一点雨
2021/04/01
5390
SpringMVC 源码分析之 DispatcherServlet
SpringMVC源码学习(三) - 请求处理的流程
在最近的一篇文章中我们大概了解了SpringMVC的九大组件,以及初始化的问题。根本初始化的发起是Spring的事件机制。而这九大组件是什么?我们先回顾一下,他们分别是文件处理器、语言处理器、主题处理器、控制器拦截器处理器、拦截器适配器、异常处理器、接口到视图(页面)处理器、视图处理器、放重复提交管理器。之前的两篇文章我们大概得了解了一下,但没有进行深入实现细节。所以今天我们试图通过一次请求来看看请求的调用链。
写一点笔记
2020/10/10
3590
SpringMVC源码学习(三) - 请求处理的流程
深入源码分析SpringMVC执行过程
首先,让我们从 Spring MVC 的四大组件:前端控制器(DispatcherServlet)、处理器映射器(HandlerMapping)、处理器适配器(HandlerAdapter)以及视图解析器(ViewResolver) 的角度来看一下 Spring MVC 对用户请求的处理过程,过程如下图所示:
田维常
2020/02/25
7910
SpringMVC工作原理流程(二)
当有请求过来,首先会先调用HttpServlet的service(ServletRequest req, ServletResponse res)方法,在service方法内部调用service(HttpServletRequest request, HttpServletResponse response)方法(这个service是重载方法,参数类型不同),FrameworkServlet对这个方法重写了。FrameworkServlet方法内部会调用父类的service(HttpServletRequest request, HttpServletResponse response)方法,父类的service(HttpServletRequest request, HttpServletResponse response)方法对不同的请求类型进行了划分,比如doGet,doPost,doXXX,FrameworkServlet对每个请求类型都做了方法重写,在方法内部,都统一调用processRequest(request, response)方法进行处理。processRequest(request, response)内部会对不同请求类型请求处理。
秋白
2019/02/21
5290
SpringMVC工作原理流程(二)
一文讲述Spring MVC的执行流程
看下这个类的全部方法,不用想一定会有一个类似于Servlet中的service方法,果然如此
闫同学
2022/10/31
3810
一文讲述Spring MVC的执行流程
【小家Spring】Spring MVC执行流程 FrameworkServlet、DispatcherServlet源码分析(processRequest、doDispatch)
本篇博文会更偏向于应用、更加宏观一些。 但是,本人还是建议,在了解Spring MVC的执行流程之前,先参阅这两篇博文: 【小家Spring】Spring容器(含父子容器)的启动过程源码级别分析(含web.xml启动以及全注解驱动,和ContextLoader源码分析) 【小家Spring】Spring MVC初始化(容器启动)时,Spring MVC九大组件初始化详解(Spring MVC的运行机制) 这样会有助于你更好的了解本文的一个流程,毕竟既会宏观的从步骤上去讲解,也会稍微微观(注意是稍微)的从源码角度去分析一下子
YourBatman
2019/09/03
1.3K0
【小家Spring】Spring MVC执行流程 FrameworkServlet、DispatcherServlet源码分析(processRequest、doDispatch)
SpringMVC源码解析(二)
在上篇文章SpringMVC源码解析(一)中,我们搭建了一个SpringBoot的启动demo,分析了SpringBoot中SpringMVC的自动配置原理以及DispatcherServlet的初始化流程。本篇文章就分析一次请求在SpringMVC中的处理流程
Java学习录
2019/09/08
4740
一文读懂Spring MVC执行流程
说到Spring MVC执行流程,网上有很多这方面的文章介绍,但是都不太详细,作为一个初学者去读会有许多不理解的地方,今天这篇文章记录一下我学习Spring MVC的心得体会
说故事的五公子
2019/10/24
1.7K0
SpringMVC源码剖析-SpringMVC执行流程
上一篇文章写得是SpringMVC组件初始化,这篇文章我们来探讨一下SpringMVC的执行流程
全栈程序员站长
2022/09/14
6170
SpringMVC源码剖析-SpringMVC执行流程
你知道从浏览器发送请求给SpringBoot后端时,是如何准确找到哪个接口的?(下篇)学废了吗?
注意: 本文 SpringBoot 版本为 2.5.2; JDK 版本 为 jdk 11.
宁在春
2022/10/31
6980
你知道从浏览器发送请求给SpringBoot后端时,是如何准确找到哪个接口的?(下篇)学废了吗?
SpringMvc简单梳理
刚开始接触springmvc的时候就听说过一个核心的类: DispatchServlet , 现在以spring-webmvc为入口探索下springmvc的核心类及流程,
eeaters
2021/11/19
4060
SpringMvc简单梳理
SpringMVC(三):SpringMVC执行流程
用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由 它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
Lansonli
2022/12/27
5530
SpringMVC(三):SpringMVC执行流程
Spring MVC请求处理过程。你这样回答保证通过面试!
SpringMVC请求处理相信大家都很熟悉了,本篇主要是基于SpringMVC处理请求的流程来阅读并调试源码,以及解决几个仅靠流程图无法解释的问题。
程序员白楠楠
2020/12/07
7630
Spring MVC介绍(一)之 Spring MVC体系结构与执行流程
Spring MVC是Spring的一个模块,包含Web MVC、Framework,Web Views,JSP等等。 其中MVC分别对应:Model,View,Controller,本质上SpirngMVC还是使用Servlet进行处理,并在其基础上进行了封装,简化了开发流程,提高易用性,并使得逻辑结构变得非常清晰。
zoro
2019/04/11
8860
Spring MVC介绍(一)之 Spring MVC体系结构与执行流程
SpringMVC源码分析
HandlerExecutionChain 包含了 DemoController.handle01 以及 0个 interceptors
huofo
2022/03/17
3650
SpringMVC源码分析
XSS事件(一)
​ 最近做的一个项目因为安全审计需要,需要做安全改造。其中自然就包括XSS和CSRF漏洞安全整改。关于这两个网络安全漏洞的详细说明,可以参照我本篇博客最后的参考链接。当然,我这里并不是想写一篇安全方面的专题。我要讲的是在做了XSS漏洞修复之后引发的一系列事件。
SecondWorld
2018/12/04
6650
SpringMVC运行原理
按照上边的执行流程图,我们可以看出一个SpringMVC整体的一个执行轮廓,下面我们具体来分析下
Arebirth
2019/09/24
6730
SpringMVC运行原理
相关推荐
SpringMVC之请求流程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验