《Spring源码深度解析》十一(2)

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

11.2.3 DispatcherServlet的逻辑处理

分析最常用的doGet()和doPost(),由DispatcherServlet父类FrameworkServlet实现

doGet和doPost方法直接调用processRequest方法

processRequest方法则将细节交给doService方法,其在处理前后做了以下工作:(记录了当前时间,用来计算web请求的处理时间)

《Spring源码深度解析》十一(2)

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.根据视图跳转页面

  • 解析视图名称

《Spring源码深度解析》十一(2)


  • 页面跳转

ModelView可以存放属性,在jsp上获取,就是在这里实现,原理为将要用到的属性放入request中


原文始发于微信公众号(不止于Java):《Spring源码深度解析》十一(2)