java源码 - SpringMVC(10)之 一次请求总结

1. Servlet

Servlet=Service+Applet

而Servlet的运行一般需要一个容器,java中常用的容器就是Tomcat。Servlet所做的工作就是在做了一层底层的Socket连接的封装,让我们可以不用管这些复杂的东西只关注于业务逻辑的处理。
感兴趣的可以看看Tomcat的底层原理

而我们知道SpringMVC的本质就是一个Servlet,但是我们要清楚其实整个过程是存在两步的:初始化+请求处理
SpringMVC已经将初始化隐藏在底层,请求处理更是处理得简单到我们只需要考虑Get等请求。其实,初始化,请求处理才是我们源码学习的主要方向。
举个例子:Tomcat初始化时,同时Spring容器是怎么初始化的,Bean是如何加入到容器的?其次,请求处理从Tomcat到SpringMVC的DispatcherServlet是怎样?
围绕初始化+请求处理,就有了方向。搞清楚这些,基本上我们都懂得了大致的代码。
其次,则是在面对多种情况时,SpringMVC是如何处理的。我们看见了,高度依赖Spring容器的MVC采用了大量的设计模式,例如:贯穿SpringMVC的模板模式,适配器模式,组合模式等。这也是一个学习的方向。

对于SpringMVC的众多组件,在2020年前后端分离的大环境下,其实有很多组件都不需要再看了。比如theme等。
但是我们看源码的时候搞清楚了吗?
ControllerAdvice,RequestBody,ResponseBody是如何处理的?
模板引擎FreeMarker又是怎样的,这些都是问题。虽然目前我只看了一遍书籍与跟着学了学源码,但是仍然有许多问题疑惑,后面再来看源码的话, 就基本上是一些零碎问题的底层源码的理解了。

2. SpringMVC

初始化:HttpServletBean、FrameworkServlet和DispatcherServlet。
在这里插入图片描述
牢记这张图就可以明白,SpringMVC是如何联系上Tomcat的,从这个类图就可以看出,HttpServletBean是联系的纽带。

连接处理:
主要在DispatcherServlet中的processRequest方法:
①调用了doService模板方法具体处理请求,doService方法在DispatcherServlet中实现;
②将当前请求的LocaleContext和ServletRequestAttributes在处理请求前设置到了LocaleContextHolder和RequestContextHolder,并在请求处理完成后恢复;
③请求处理完后发布一个ServletRequestHandledEvent类型的消息。

举个例子:这里的问题为什么要拿到xxxHolder中?
以RequestContextHolder为例子:
在这里插入图片描述
从属性看到xxx类的Holder基本上字段和方法都是静态的,而且出现了ThreadLocal,立马就可以想到其是于线程绑定的一些属性可以通过全局拿到。
如何通过全局拿到呢?就是如下的静态方法:如何保证每次拿到的属性都是Tomcat线程相关的呢?ThreadLocal了解吗?
在这里插入图片描述
举一反三:XXXHolder在其他框架的使用。ThreadLocal了解。线程相关。
抛开框架我可以得到以上万金油。看完SpringMVC源码,当我再遇到其他框架时,很快就可以产生联想理解。


DispatcherServlet在doServic方法中将webApplicationContext、localeResolver、theme-Resolver、themeSource、FlashMap和FlashMapManager设置到request的属性中以方便使用,然后将请求交给doDispatch方法进行具体处理。

DispatcherServlet的doDispatch方法按执行过程大致可以分为4步:
①根据request找到Handler;
②根据找到的Handler找到对应的HandlerAdapter;
③用HandlerAdapter调用Handler处理请求;
④调用processDispatchResult方法处理Handler处理之后的结果;

等会我会来一次请求的debug来完成这次的学习。
下面来接着回顾:
Handler、HandlerMapping和HandlerAdapter这三者,其实在MVC中属于比较难的内容了,因为请求的多样性处理基本就在这儿。
这里我可以坦白:
在这里插入图片描述
但是没关系,目前仍然掌握全局。。。有闲心了再来看看就是了。

3. DeBug

还是围绕初始化,请求处理:

3.1 初始化

请注意:没有配置ContextLoaderListener

在HttpServletBean的init方法处打断点,然后启动tomcat:
org.springframework.web.servlet.HttpServletBean#init
在这里插入图片描述
来看看调用栈:
在这里插入图片描述
看看所处的包结构,是不是看出什么来了?

接着找到org.springframework.web.servlet.FrameworkServlet#initServletBean:
在这里插入图片描述

在这里插入图片描述

接下来怎么打断点?我也忘记了,没关系:
在这里插入图片描述

第一个: Step Over (F8):步过,一行一行地往下走,如果这一行上有方法不会进入方法。
蓝色 :Step Into (F7):步入,如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内,不会进入官方类库的方法,如第25行的put方法。
红色:Force Step Into (Alt + Shift + F7):强制步入,能进入任何方法,查看底层源码的时候可以用这个进入官方类库的方法。

顾名思义,开始初始化Web容器:
在这里插入图片描述
此时是没有Web容器的,到这一步创建一个新的Web容器
在这里插入图片描述
看看容器有什么,其实就是Spring+Servlet的上下文,并加载入相应的Bean;
在这里插入图片描述
其中,DispatcherServlet根据contextConfigLocation配置的classpath下的xxxmvc.xml文件初始化了Spring MVC中的组件。这一步是在容器创建完成吼的那个方法内调用的。

随后刷新Web容器:
在这里插入图片描述
随后不断下一步,SpringMVC的内容就差不多完了。这里其实需要Spring的一些知识。

3.2 一个请求

首先我们人为的来模拟一次请求:

Tomcat收到请求后,应该是交给DispatcherServlet来处理,我们又知道Servlet顶层处理请求的方法是Service()。
那么我们来找DispatcherServlet的父类中谁有Service方法,很容易我们找到
org.springframework.web.servlet.FrameworkServlet#service
在这里插入图片描述
在processRequest()处打一个断点,继续跟踪。
org.springframework.web.servlet.FrameworkServlet#processRequest
在这里插入图片描述
为什么在doService处打断点?因为这是一个留给DispatcherServlet实现的模板方法。
在这里插入图片描述

那么我们进入DispatcherServlet:

org.springframework.web.servlet.DispatcherServlet#doService
在这里插入图片描述
在doDispatch做分发,进入doDispatch,org.springframework.web.servlet.DispatcherServlet#doDispatch在这里插入图片描述
接着来启动,看看是否是这样,如何验证,其实很简单。一步一步玩下,或者直接只打最后一个断点,看调用栈。

发送一个请求:调用栈目前
在这里插入图片描述
我接着往下执行一步,其实出现了错误。这是个好现象。
在这里插入图片描述
调用栈调用的是:
在这里插入图片描述
其实是由
在这里插入图片描述
来处理是doGet还是doPost方法,前提是
在这里插入图片描述
请求方法是PATCH请求。很明显不是,那么就调用父类的Service()方法,然后由HttpServlet来处理请求,判断当前方法是Get请求,交由子类的FrameworkServlet的重载方法doGet来执行。
而我们之前人为的断点处理,是直接进入了processrequest方法,这样是不对的。
那么现在我们进入了doService:
在这里插入图片描述
继续往下执行:
在这里插入图片描述
在这里插入图片描述

再来看调用栈:
在这里插入图片描述
这个调用顺序就出来了。至此初始化+请求处理就完接了。其实学下来。掌握这个大体的流程就可以了。
在这里插入图片描述

4. SpringBoot

todo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值