在平时开发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. 【前端】Vue2全家桶案例《看漫画》之四、漫画页

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/vue_vux_app_4.html 项目github地址:https://github.com/shamoyuu/ ...

  2. 2.2 HOST主桥

    本节以MPC8548处理器为例说明HOST主桥在PowerPC处理器中的实现机制,并简要介绍x86处理器系统使用的HOST主桥. MPC8548处理器是Freescale基于E500 V2内核的一个P ...

  3. FFmpeg-音频和视频应用程序的瑞士军刀

    FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进的音频/视频编解码库l ...

  4. 基于Jenkins+Git+Gradle的Android持续集成

    本文参考了: http://my.oschina.net/uboluo/blog/157483 http://java.dzone.com/articles/automating-continuous ...

  5. 进程中调用CreateMutex

    // TestStorage.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Windows.h> #inc ...

  6. SetCooperativeLevel函数介绍(设置协作等级)

    函数声明 function SetCooperativeLevel(hWnd: HWND; dwFlags: DWORD): HResult; stdcall; 参数介绍 hWnd        Di ...

  7. directX枚举系统设备类

    void CSysEnumDlg::DisplayFullCategorySet(void){    USES_CONVERSION;    HRESULT hr;    IEnumMoniker * ...

  8. 芝麻HTTP:Python爬虫实战之爬取糗事百科段子

    首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的 ...

  9. CentOS恢复系统启动grub1.5,2阶段

    1.模拟CentOS7系统/boot下文件全丢失 rm -rf  /boot/* 2.重启系统,并进入救援模式 3.将救援光盘路径切换回原来的系统磁盘根路径 chroot /mnt/sysimage ...

  10. asp.net mvc razor布局页中a标签的href的跳转问题

    笔者做了一个文件上传系统,文件上传后,保存在wwwroot目录的file文件夹中,并把该文件的路径保存到数据库中, 如这样的一个路径保存在数据库: file/b775f487-0127-41e0-9d ...