在平时开发SpringtMVC程序时,在Controller的方法上,通常会传入如Map、HttpServletRequest类型的参数,并且可以方便地向里面添加数据。同时,在Jsp中还可以直接使用request等对象方便地获取出来。

如下面2图所示:

可问题是:@RequestMapping 方法中的 Map、HttpServletRequest等参数信息是如何封装和传递的?

带着这个问题,写了个简单的Demo,来进行源码调试。

Demo代码地址:

https://github.com/cyhbyw/springMVC_atguigu_TongGang

工程名称:

springMVC_DebugSourceCode

===============================以下是源码调试=========================================

01.首先,浏览器发出的请求到DispatcherServlet;然后,找到合适的HandlerAdapter(此处是RequestMappingHandlerAdapter);然后调用RequestMappingHandlerAdapter的handle()方法。此时,方法堆栈从Line959开始。

02.还是在DispatcherServlet的Line959的doDispatch()方法内,又调用了几个方法,到达invokeForRequest()方法;顾名思义,此方法会真正的调用Request方法(即Controller中的方法);不过,先会在Line128解析参数。

03.解析参数的方法又会走到Line161.

04.再经过两个方法的调用,可以看到上述的参数解析方法是直接返回了 mavContainer.getModle()

05.而getModel() 方法返回 defaulutModel 的成员变量。

06. defaulutModel 其实就是一个 BindingAwareModelMap

07.回到刚才的Line161,可以看到 args[i] 指向了刚才得到的BindingAwareModelMap,且内存地址是5010。

08.再返回一层,此处的 Object[] args 还是BindingAwareModelMap@5010,且其中的元素为空;此处Line136的 doInvoke(args) 方法就是通过反射调用真实的Controller中的方法。

09.真实Controller方法调用返回后,可以看到 mavContainer 对象中的 defaultModel 属性已经被赋值,且这个值就是BindingAwareModelMap@5010,与args是同一个对象(非常重要)!!!!

(备注:SpringMVC是如何为mavContainer 对象中的 defaultModel 属性赋值的,最开始调试了很久也没有发现,心想着,它既然是个Map,那应该是调用setXXX(), put(), putAll()这样的方法赋值进去的,但调试了很久始终没发现这样的方法被调用;同时,也可以确定它是在Line136行调用后就被赋值的;最后猜测,是同一个对象引用;现在,证明确实如此)

再啰嗦一句,其实就是:Line128的 Object[] args 变量指向了 mavContainer 对象的 defaultModel 属性!所以在将 args 通过Line136反射调用真实的Controller方法并填充数据后,defaultModel中也就有了相应数据!

10.控制台打印的入参Map其实也是BindingAwareModelMap(遗憾的是没有拿到内存地址;但还是可以辅助证明09中的结论)

11.真实Controller方法调用完成后,开始处理返回值

12.设置视图名称

13.准备创建ModelAndView对象

14.从 mavContainer 中取出Model数据,并通过构造函数传入ModelAndView

15.已经获得ModelAndView对象,进行后续操作(如渲染);注意,此时DispatcherServlet中的方法堆栈从Line971开始。

16.准备渲染

17.得到View对象

18.遍历 viewResolvers 找到一个合适的就返回给17步中的View对象

19.准备渲染

20.将Model数据暴露为RequestAttribute

21.暴露的本质其实是:request.setAttribute(modelName, modelValue)

22.最后是一个转发操作

SpringtMVC运行流程:@RequestMapping 方法中的 Map、HttpServletRequest等参数信息是如何封装和传递的(源码理解)的更多相关文章

  1. .NET Core 3.0之深入源码理解Startup的注册及运行

    原文:.NET Core 3.0之深入源码理解Startup的注册及运行   写在前面 开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程 ...

  2. 【春华秋实】深入源码理解.NET Core中Startup的注册及运行

      写在前面 开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程序的起点.通过使用Startup,可以配置化处理所有向应用程序所做的请求的 ...

  3. Spring中@Transactional事务回滚(含实例详细讲解,附源码)

    一.使用场景举例 在了解@Transactional怎么用之前我们必须要先知道@Transactional有什么用.下面举个栗子:比如一个部门里面有很多成员,这两者分别保存在部门表和成员表里面,在删除 ...

  4. 在.NET Core中三种实现“可插拔”AOP编程方式(附源码)

    一看标题肯定会联想到使用动态编织的方式实现AOP编程,不过这不是作者本文讨论的重点. 本文讨论另外三种在netcore中可实现的方式,Filter(过滤器,严格意义上它算是AOP方式),Dynamic ...

  5. MVC中使用SignalR打造酷炫实用的即时通讯功能附源码

    前言,现在这世道写篇帖子没个前言真不好意思发出来.本贴的主要内容来自于本人在之前项目中所开发的一个小功能,用于OA中的即时通讯.由于当时走的太急,忘记把代码拿出来.想想这已经是大半年前的事情了,时间过 ...

  6. Asp.net Core中SignalR Core预览版的一些新特性前瞻,附源码(消息订阅与发送二进制数据)

    目录 SignalR系列目录(注意,是ASP.NET的目录.不是Core的) 前言 一晃一个月又过去了,上个月有个比较大的项目要验收上线.所以忙的脚不沾地.现在终于可以忙里偷闲,写一篇关于Signal ...

  7. 从Mybatis源码理解jdk动态代理默认调用invoke方法

    一.背景最近在工作之余,把开mybatis的源码看了下,决定自己手写个简单版的.实现核心的功能即可.写完之后,执行了一下,正巧在mybatis对Mapper接口的动态代理这个核心代码这边发现一个问题. ...

  8. 2018.11.20 Struts2中对结果处理方式分析&struts2内置的方式底层源码剖析

    介绍一下struts2内置帮我们封装好的处理结果方式也就是底层源码分析 这是我们的jar包里面找的位置目录 打开往下拉看到result-type节点 name那一列就是我们的type类型取值 上一篇博 ...

  9. Winforn中DevExpress的TreeList中显示某路径下的所有目录和文件(附源码下载)

    场景 Winform中DevExpress的TreeList的入门使用教程(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...

随机推荐

  1. 《android开发艺术探索》读书笔记(十三)--综合技术

    接上篇<android开发艺术探索>读书笔记(十二)--Bitmap的加载和Cache No1: 使用CrashHandler来获取应用的crash信息 No2: 在Android中单个d ...

  2. JavaScript的this和作用域

    本文主要讨论一下JS的作用域和this关键字.作用域,就是你的方法或者变量可访问的区域,是他们执行的上下文.如果你见过这样的代码: function someFunc() { var _this = ...

  3. Subsequence Count (线段树)

    Time Limit: 1000 ms   Memory Limit: 256 MB Description 给定一个01串 $S_{1 \cdots n}$ 和 $Q$ 个操作. 操作有两种类型: ...

  4. ANTD mobile源码分析 -- popover

    最近的开发中要用到很多的各式各样的组件.但是发现ant design mobile(后面简称ANTDM)里很多的资源.于是就分析一下,学习学习. ANTDM直接使用了typescript,没有用ES2 ...

  5. PaddlePaddle︱开发文档中学习情感分类(CNN、LSTM、双向LSTM)、语义角色标注

    PaddlePaddle出教程啦,教程一部分写的很详细,值得学习. 一期涉及新手入门.识别数字.图像分类.词向量.情感分析.语义角色标注.机器翻译.个性化推荐. 二期会有更多的图像内容. 随便,帮国产 ...

  6. MySQL更改数据库表的存储引擎

    MySQL更改数据库表的存储引擎 1.查看表的原存储引擎 show create table user; 'user', 'CREATE TABLE `user` (\n `id` int(11) N ...

  7. ubuntu16.04搭建ftp服务器

    因为习惯了vs进行开发,所以对于Linux的代码编辑开发都在vs里面进行,通常我们都是ssh远程登录到Linux,使用ftp或者sftp共享Linux目录里面的文件方便对文件的共享,这里介绍一下在ub ...

  8. 几个平台环境里视频编解码和图像scale的硬件加速的方法

    记录一下遇到几个平台里的视频编解码和图像scale的硬件加速的方法 1,intel平台当包含GEN系列的集成GPU时,可用libva实现视频codec.颜色空间转换和图像scale的硬件加速,具体可使 ...

  9. httpclient案例一(调用识别接口)

    public Map<String, Object> pictureRecognition(String recotype, MultipartFile imageFile) { Stri ...

  10. 移动端开发底部元素margin-bottom失效解决办法

    一.情景 记得之前开发一个微信端页面时,发现页面底部元素margin-bottom在ios下失效,在安卓内正常...... 1.safari浏览器内页面底部元素设置margin-bottom失效: 2 ...