《Spring源码深度解析》十一(2)
11.2.3 DispatcherServlet的逻辑处理
分析最常用的doGet()和doPost(),由DispatcherServlet父类FrameworkServlet实现
doGet和doPost方法直接调用processRequest方法
processRequest方法则将细节交给doService方法,其在处理前后做了以下工作:(记录了当前时间,用来计算web请求的处理时间)
doService则由DispatcherServlet实现,此方法也是做一些准备工作,即将一些已经初始化的功能辅助工具变量,比如localeResolver ,themeResolver等设置在request 属性中,而这些属性会在接下来的处理中派上用场,然后,此方法调用doDispatcher,开始完整的请求处理过程:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception{
...
}
请求处理流程:
11.2.3.1.MultipartContext类型的request处理
11.2.3.2.根据request信息寻找对应的Handler
-
根据request查找对应的Handler
-
加入拦截器到执行链
11.2.3.3.没找到对应的Handler的错误处理
11.2.3.4.根据当前Handler寻找对应的HandlerAdapter
11.2.3.5.缓存处理
11.2.3.6.HandlerInterceptor的处理
11.2.3.7.逻辑处理
11.2.3.8.异常视图的处理
11.2.3.9.根据视图跳转页面
-
解析视图名称
-
页面跳转
下面来一步步分析
11.2.3.1.MultipartContext类型的request处理
//如果是MultipartContent类型的request
//则转换request为MultipartHttpServletRequest类型的request
processedRequest = checkMultipart(request);
11.2.3.2.根据request信息寻找对应的Handler
根据URL找到匹配的Controller并返回,如果没有找到对应的Controller处理器那么程序会尝试去查找
配置中的默认处理器。
当查找的controller为String类型时,那就意味着返回的是配置的bean名称, 需要根据bean名称查找对应的bean ,最后,还要通过getHandlerExecutionChain方法对返回的Handler 进行封装, 以保证满足返回类型的匹配。
-
根据request(URL)查找对应的Handler
考虑了直接匹配与通配符两种情况
buildPathExposingHandler方法将Handler封装成了HandlerExecutionChain类型
此处使用了链处理机制,AOP中也有使用,非常nice的设计
-
加入拦截器到执行链
11.2.3.3.没找到对应的Handler的错误处理
11.2.3.4.根据当前Handler寻找对应的HandlerAdapter
默认情况下普通的web请求会交给SimpleControllerHandlerAdapter去处理
获取适配器的思路:遍历所有适配器来选择合适的适配器并返回它
11.2.3.5.缓存处理
Last-Modified缓存机制:记录用户最后进行更新操作的时间,实现LastModified接口即可
Spring判断是否过期就是根据请求的“If-Modified-Since”是否大于等于当前的getLastModified方法的时间戳,如果是, 则认为没有修改。
11.2.3.6.HandlerInterceptor的处理
进行前置处理、后置处理和自定义拦截器,即此处为拦截器的实现原理
11.2.3.7.逻辑处理
通过适配器中转调用Handler调用用户逻辑并返回视图
11.2.3.8.异常视图的处理
11.2.3.9.根据视图跳转页面
-
解析视图名称
-
页面跳转
ModelView可以存放属性,在jsp上获取,就是在这里实现,原理为将要用到的属性放入request中
原文始发于微信公众号(不止于Java):《Spring源码深度解析》十一(2)