手记

DispatcherServlet-静态资源服务原理(四)

在请求静态资源文件的时候,Spring内部是如何实现的呢?之前对这个问题,有疑问,但如果是自己处理静态的资源都是统一的使用IOUtils.copy(input,output)中去,想了解下Spring内部是如何做的。

带着疑问阅读下源码,果不其然,一起看下

分析

之前我们提到了DispatcherServlet的doDispatcher大致流程,这次我们以静态资源文件为例,再看下。

  1. 在dispatcher-servlet.xml配置文件里面,配置静态资源的路径。然后在js目录下新建一个index.js文件

<mvc:resources mapping="/js/**" location="/js/" />
  1. 启动项目,调试在getHandler这一步,我们可以看到配置的HandlerMappings,其中SimpleUrlHandlerMapping是我们在xml配置文件中配置的,我们写几个resource的映射,就有几个SimpleUrlHandlerMapping对象。

image.png

像RequestMappingHandlerMapping,根据请求的路径获取Bean对应的HandlerMethod,然后封装。
BeanNameUrlHandlerMapping再调试的时候还未遇到。
SimpleUrlHandlerMapping根据我们在配置文件里面的定义,可以看到获取到对应的ResourceHttpRequestHandler.


image.png

  1. 获取静态资源的HandlerAdpater. 这些都是之前分析doDispatch提到的


    image.png

三个不同的Adpater内部实现的support机制不同,如果support返回true则获得对应的Adapter.
支持ResourceHttpRequestHandler的Handler只有HttpRequestHandlerAdapter,看他们的名字差不多就可以对应上来。

  1. 拦截器预处理,不多说了

  2. 进行处理HanderAdapter.handler(request,response,handler)
    静态资源的HandlerAdpater处理很少,直接交给Handler进行的处理,没有额外的操作。


    image.png

handleRequest内部处理如下:

  • getResource获取路径对应的静态资源,文件

  • 检查请求是否合法

  • 判断是否要加cache的Http Header

  • 根据Http是否有Range头部,不管有无,都通过StreamUtils进行流拷贝。中间又利用到ResourceHttpMessageConverter.

HttpMessageConterver可以转换Request和Response的一些内容,细节以后再讨论

image.png

  1. 将静态资源文件通过流的方式输出到输出流之后,ModelAndView值为null,所以不会对视图进行处理

  2. Handler的拦截器进行postHandler处理,之前提到过,这里不多说了。

  3. 处理分发结果,errorView,exception,modelandview都为null,也就是都不处理,最后进行拦截器的triggerAfterCompletion操作

  4. 进行最后的清理工作,请求完成

回顾

如果明白doDispatcher的流程之后,再去看静态资源的处理,就简单很多,因为服务静态资源也是doDispatch的一部分。

服务静态资源简单来说:
首先,根据我们定义的resorce映射,内部会创建SimpleUrlHandler,在获取到Handler之后,静态资源的HandlerAdpater也比较简单,它的Adpater仍然是把操作交给Handler处理。

Handler内部因为是静态资源,没有太多的逻辑操作,只是对Http的请求头做一些判断,最后都是由ResourceHttpMessageConverter将资源通过流的方式输出到Resouce.

后续基本上只是拦截器稍微工作一下,其余基本上都是跳过的操作

总结

Spring MVC对静态资源的处理,相对简单一些。

0人推荐
随时随地看视频
慕课网APP