SpringMVC处理请求
HttpServletBean
从HttpServletBean的结构中可知,其没有重写service,doXXX等处理请求方法,所以HttpServletBean没有具体处理请求
FrameworkServlet
FrameworkServlet重写了HttpServlet的这些方法
可以看到Service之中将除了PATCH方法的所有请求都集中到processRequest中进行处理。
这和HttpServlet将不同请求按类型分到不同的方法中正好相反。为什么要这么做?其实SpringMVC对不同类型的请求划分的很好,这里只是应该有其他的事情要做,并且将结构分得更为清晰。先看processRquest
核心的是doService()模板方法,这个方法在DispatchServlet中实现。在doService前后还做了一些事情,这个就是装饰器设计模式。
在doService()之前是将请求之前的LocaleContext和RequestAttribute保存,然后获取当期请求的LocaleContext和RequestAttribute并设置上,doService()处理之后在finally中使用resetContextHolder再进行恢复。
最后发送一个ServletRequestHandledEvent。
LocaleContextHolder、RequestAttributesHolder
LocaleContext中存放的是本地化信息
首先要提到的一点是LocaleContextHolder是个abstract类,其中的所有方法都是static方法,可以直接调用,而且没有父类也没有子类。也即是不能对其进行实例化,只能调用其中的方法,这种设计是值得学习的。(ps:我通常写Django代码的时候写了很多的工具函数,其实没有做过封装,是很不好的。)
在LocaleContextHolder中封装了两个属性
都是ThreadLocal类型的,第二个可以被子线程继承,关于ThreadLocal可以参考:
另外LocalContextHolder提供了get/setLocal方法
举个例子程序中如果要使用到Locale的时候首先可以从request中获取,request.getLocale(),但是如果是在Service层中的话就没有request对象了,需要Controller将request传进来。这个就太麻烦了,而且需要修改Service层的接口。这个时候可以直接使用LocaleContextHolder.getLocale()获取Locale对象
RequestAttributes是Spring的一个接口
通过RequestAttributes可以get/set/removeAttributes,根据scope参数判定是操作的reques还是session
FrameworkServlet使用的是ServletRequestAttributes,看下其set方式(get/remove类似)
这里判定了一个属性isRequestActive(),当调用了requestComplete()方法后request的requestActive就变成了false,可以参看FrameworkServlet中finally中的调用。其实很容易立即,request执行完毕之后就是非active的了。
这里提出一个问题:我想Attributes应该是个Map属性,用来设置key-value,但是一直没有找到这个属性,在HttpServletRequest中没有找到,具体存储在哪里现在还不知道。。
在说一下RequestAttributesHolder,其和LocaleContextHolder的设计类似:
同样的可以在Service层中通过RequestAttributesHolder获取Request
HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
HttpServletResponse resp = ((ServletWebRequest)RequestContextHolder.getRequestAttributes()).getResponse();
可以参考Spring MVC 中几种获取request和response的方式
publishRequestHandledEvent
在FrameworkServlet中的finally中调用了:
当publishEvent为true的时候就发送消息,在web.xml中publishEvent的配置默认为true。
对于监听这个消息值需要继承ApplicationListener接口,并实现onApplicationEvent方法
对于使用参考下这篇文章:利用spring的ApplicationListener监听某一类事件的发生
DispatchServlet
DispatchServelet是SpringMVC的核心类,所有的顶层设计都在这里。
通过之前的分析可以知道DispatchServlet中执行处理方法的入口是doService
设置属性中前面4个和Handler/View有关,后面的三个属性和flashMap有关,主要用与Redirect转发时参数的传递。具体之后研究
由上述代码可知doService()将具体的工作转发给了doDispatch()
还没有评论,来说两句吧...