SpringMVC处理请求

HttpServletBean

SpringMVC处理请求_第1张图片
从HttpServletBean的结构中可知,其没有重写service,doXXX等处理请求方法,所以HttpServletBean没有具体处理请求

FrameworkServlet

SpringMVC处理请求_第2张图片
FrameworkServlet重写了HttpServlet的这些方法
这里写图片描述
可以看到Service之中将除了PATCH方法的所有请求都集中到processRequest中进行处理。
这和HttpServlet将不同请求按类型分到不同的方法中正好相反。为什么要这么做?其实SpringMVC对不同类型的请求划分的很好,这里只是应该有其他的事情要做,并且将结构分得更为清晰。先看processRquest
SpringMVC处理请求_第3张图片
SpringMVC处理请求_第4张图片
核心的是doService()模板方法,这个方法在DispatchServlet中实现。在doService前后还做了一些事情,这个就是装饰器设计模式。
在doService()之前是将请求之前的LocaleContext和RequestAttribute保存,然后获取当期请求的LocaleContext和RequestAttribute并设置上,doService()处理之后在finally中使用resetContextHolder再进行恢复。
最后发送一个ServletRequestHandledEvent。

LocaleContextHolder、RequestAttributesHolder

LocaleContext中存放的是本地化信息
SpringMVC处理请求_第5张图片
SpringMVC处理请求_第6张图片
SpringMVC处理请求_第7张图片
首先要提到的一点是LocaleContextHolder是个abstract类,其中的所有方法都是static方法,可以直接调用,而且没有父类也没有子类。也即是不能对其进行实例化,只能调用其中的方法,这种设计是值得学习的。(ps:我通常写Django代码的时候写了很多的工具函数,其实没有做过封装,是很不好的。)

在LocaleContextHolder中封装了两个属性
这里写图片描述
都是ThreadLocal类型的,第二个可以被子线程继承,关于ThreadLocal可以参考:

另外LocalContextHolder提供了get/setLocal方法
SpringMVC处理请求_第8张图片

举个例子程序中如果要使用到Locale的时候首先可以从request中获取,request.getLocale(),但是如果是在Service层中的话就没有request对象了,需要Controller将request传进来。这个就太麻烦了,而且需要修改Service层的接口。这个时候可以直接使用LocaleContextHolder.getLocale()获取Locale对象

RequestAttributes是Spring的一个接口
SpringMVC处理请求_第9张图片
通过RequestAttributes可以get/set/removeAttributes,根据scope参数判定是操作的reques还是session
FrameworkServlet使用的是ServletRequestAttributes,看下其set方式(get/remove类似)
SpringMVC处理请求_第10张图片
这里判定了一个属性isRequestActive(),当调用了requestComplete()方法后request的requestActive就变成了false,可以参看FrameworkServlet中finally中的调用。其实很容易立即,request执行完毕之后就是非active的了。
这里提出一个问题:我想Attributes应该是个Map属性,用来设置key-value,但是一直没有找到这个属性,在HttpServletRequest中没有找到,具体存储在哪里现在还不知道。。
SpringMVC处理请求_第11张图片

在说一下RequestAttributesHolder,其和LocaleContextHolder的设计类似:
SpringMVC处理请求_第12张图片
SpringMVC处理请求_第13张图片
同样的可以在Service层中通过RequestAttributesHolder获取Request

HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
HttpServletResponse resp = ((ServletWebRequest)RequestContextHolder.getRequestAttributes()).getResponse();

可以参考Spring MVC 中几种获取request和response的方式

publishRequestHandledEvent

在FrameworkServlet中的finally中调用了:
这里写图片描述
SpringMVC处理请求_第14张图片
当publishEvent为true的时候就发送消息,在web.xml中publishEvent的配置默认为true。
对于监听这个消息值需要继承ApplicationListener接口,并实现onApplicationEvent方法
对于使用参考下这篇文章:利用spring的ApplicationListener监听某一类事件的发生

DispatchServlet

DispatchServelet是SpringMVC的核心类,所有的顶层设计都在这里。
通过之前的分析可以知道DispatchServlet中执行处理方法的入口是doService
SpringMVC处理请求_第15张图片
设置属性中前面4个和Handler/View有关,后面的三个属性和flashMap有关,主要用与Redirect转发时参数的传递。具体之后研究

由上述代码可知doService()将具体的工作转发给了doDispatch()

SpringMVC处理请求_第16张图片
SpringMVC处理请求_第17张图片

你可能感兴趣的:(springmvc)