目标项目先部署到Tomcat上

1、将项目打包

选项中有web application exploded,这个是以文件夹形式(War Exploded)发布项目,选择这个,发布项目时就会自动生成文件夹在指定的output directory,
如果选web application archive,就是war包形式,每次都会重新打包全部的,将项目打成一个war包在指定位置;
image.png
image.png

2、Tomcat上添加要发布的项目

image.png

如果没有做第二步则会报如下的404

原始服务器没有找到目标资源的当前表示,或者不愿意透露存在该目标资源

如果配置完毕,那么就可以启动Tomcat了。

image.png

重要时机点分析如下

断点准备

1、先在要执行的业务逻辑处打断点,当断点停在此处,则结合调用栈进行分析
image.png

2、在页面处也打上断点,看什么时候调过来
image.png
打完断点,然后就可以debug启动

1)Handler方法的执行时机剖析

发送一个请求,通过调用栈查看它调用流程

image.gifimage.png
其实是先调整到jsp页面的,放行后跳到后台

image.png

通过调用栈看业务逻辑执行的时机点

从下面一直往上看,发现最后是通过doDispathch去执行后续Handler的事情,也就是doDispathch是核心的核心。doDispathch方法中的1052行代码完成handler方法的调用

image.pngimage.gif

思考:

1、调用ha.handle就能返回ModelAndView,那么传入的参数mappedHandler.getHandler()哪里来的
2、用ha去调用,那么ha又是从哪里来的
3、根据上面两个疑问,往上找代码,
image.png
image.png

通过调用栈看页面渲染的时机点

image.png

重要的时机点找出来了,可以正向去看

在doDispatch打上断点,重新请求,看其核心步骤

1、调用getHandler方法返回的是执行链

执行链包含着拦截器
image.png

2、调用getHandlerAdapter方法返回适配器

image.png

3、通过适配器的调用handle方法返回ModelAndView

执行链为参数,用返回的适配器去调用handle方法,返回ModelAndView
image.png

4、调用processDispatchResult去渲染视图

image.png

当调用processDispatchResult方法的时候,接下来就跳到页面了
image.png
说明是渲染页面的。

Spring MVC处理请求的大致流程(doDispatch方法核心步骤) :

1)调用getHandler() 获取到能够处理当前请求的执行链HandlerExecutionChain (Handler+拦截器)
如何去getHandler的?
2) 调用getHandlesAdapter(); 获取能够执行2) 中Handler的适配器。 如何去getHandlerAdapter的?
3) 适配器调用Hapdler执行ha.handle(总会返回一个ModelAndView对象),而且执行链也为参数哦
4) 调用processDispatchResult() 方法完成视图渲染跳转,执行这个方法会跳到页面的哦

2)getHandler方法的分析

在getHandler方法上打个断点,重新请求进去

image.png

通过遍历获取数据并封装执行链

image.png

如何在刚进来的代码看重点呢?

image.png

image.png

把拦截器添加到执行链中

image.png

image.png

到此,也就清晰知道getHandler方法返回执行链的流程了。

3)getHandlerAdapter方法的分析

调用getHandlerAdapter方法返回适配器,进去看看其逻辑

image.png

遍历处理器适配器
image.png

image.png

发现它直接返回了。到此也就知道他适配器的底层执行逻辑。看请求的是属于三种类型的哪一种,就具体调用哪一种的方法,获取适配器。

4)什么时候进行组件初始化呢?

主要是加载相应的类形成对应的Bean对象

image.png

看onRefresh方法它执行链和时机点

打上断点,Debug启动,观察调用栈
image.png

image.png

看一下initHandlerMappings的初始化

就是将组件所对应的加载成Bean对象
if (this.detectAllHandlerMappings) 默认就是true的,找所有父类实现HandlerMappings的类
image.png如果都找不到,就用默认实image.png

默认加载的组件

image.png

image.png

在静态代码块加载

image.png

全局搜索DispatcherServlet.properties即可找到默认的配置了

其他的组件初始化也是差不多如同此流程。

看一下initMultipartResolver组件

多部件组件,用于文件上传的。这个名字是配置好的,它就会去按这个名字去查找。
image.png

5)handler方法执行细节剖析

image.png

里面还调用了一层,继续进入

image.png

先执行,根据返回结果的代码行来找目标代码行

image.png

一路走下来,这里调用invoke方法

image.png

image.png

先执行获取参数的数组

image.png

到里面去取值

image.png

image.png

image.png

image.png

image.png

6)processDispatchResult方法的执行细节剖析

image.png

通过参数出传入的,肯定不为空
image.png

先创建一个视图名,然后获取数据封装给视图名
image.png

看一下真正解析的方法
image.png
如果缓存是空的就自己创建
image.png
进入,看看如何创建的
判断是否是重定向、或者请求转发、根据不同的情况封装成不同的View实现
image.png

调用父类的重载方法,继续进入
image.png

这里看到了一个buildView,构建视图
image.png
调用父类的,继续进入
image.png

把逻辑视图名转为物理视图名

加上前缀后缀等信息
image.png

到此,一路返回
==================
返回了物理视图后,对物理视图进行渲染

image.png

需要渲染的数据放入进去image.png

然后暴露一些东西出去
image.png

循环model的数据放入到request的域中
所以在前台jsp域中能通过request域来获取的原因。
image.png

分发,路径已经给他了,跳到对应的页面上去
image.png

这整个就是试图渲染的流程