Tomcat中对静态资源的处理教程

  

  

Tomcat中的请求都是由Servlet处理,静态资源也不例外。在默认的网络。xml中,配置了一个DefaultServlet用于处理静态资源,它支持缓存和断点续传。

  

DefaultServlet的基本处理过程如下:

  
      <李>查找资源是否存在缓存李   <李>检查是否满足可选,如果头域指定的条件   <李>设置响应头域,如内容类型,内容长度,ETag, last - modified李   <李>检查是否满足Sendfile的条件,否则将内容拷贝到输出流中李   
  

接下来主要分析资源缓存的设计和实现,以及如果头域的处理。

  


  

  

访问磁盘的速度远远低于访问内存的速度,所以适当的缓存一部分静态资源能够让系统快速响应。

  

Tomcat在6.0.53版本实现静态资源的处理时,借助了JNDI的一些API(但在使用时感觉与JNDI的关系不大),相关类图及核心方法和属性如下:

  

 Tomcat中对静态资源的处理教程

  

缓存相关的类:

  
      <李> ResourceCache:缓存实现,提供了资源查找,加载,销毁的功能李   <李> CacheEntry:一个缓存条目,包含缓存名称,如/tomcat.gif资源和资源的属性以及对应的目录   
  

资源目录相关的类是:

  
      <李> EmptyDirContext:主要用于嵌入式模式,行为就像没有可用资源一样李   <李> FileDirContext:基于文件系统的资源目录服务李   <李> WARDirContext:基于战争文件的目录服务李   <李>资源:封装了资源内容,主要有字节数据和输入流李   <李> ResourceAttributes:资源属性,主要有内容长度和最后修改时间李   <李> ProxyDirContext:资源缓存和目录服务的代理,提供查找资源缓存,校验缓存是否过期等功能李   
  

默认情况下,缓存最大为10 MB,单个缓存资源最大为512 KB,缓存的TTL为5 s。

  

一般的,在Mapper映射到处理静态资源的包装器时,会引起资源的加载,基本的方法调用情况如下:

        映射器。地图(MessageBytes MessageBytes MappingData)   └─Mapper.internalMap (CharChunk CharChunk MappingData)   └─Mapper.internalMapWrapper (Mapper $上下文、CharChunk MappingData)   └─ProxyDirContext.lookup(字符串)   └─ProxyDirContext.cacheLookup(字符串)   └─ResourceCache.lookup(字符串)   └─ResourceCache。找到(CacheEntry[],字符串)      

缓存资源插入内部数组时是有序的,找到方法就是通过资源名二分查找缓存,资源名就是请求路径,此时有两种情况,缓存命中和未命中。

  

缓存未命中,在cacheLookup方法中会新建一个CacheEntry对象,调用cacheLoad方法加入到ResourceCache的缓存数组中,加入前会对缓存条目进行以下操作:

  
      <李>获取并初始化缓存资源属性,主要是文件的contentLength和lastModified李   <李>如果文件长度小于512 kb,那么将文件内容加载到内存中李   <李>标记缓存存在,设置缓存时间戳   
  

缓存命中,会对缓存条目进行校验:

  
      <李>检查是否过期,当前时间大于缓存条目设置的时间戳   <李>如果过期,再检查资源内容是否修改李   <李>如果修改,清除这个缓存,读取最新内容李   
  

以上就是资源缓存简单的处理过程。

  


  

  

客户端接收并缓存请求的资源,,当再次请求此资源时,服务端根据特定的请求头域来验证资源是否修改,没有变动,则只返回一个304 Not Modified响应,否则返回资源的内容,从而节省带宽。

  

用于资源验证的头域有两种,分别是:last - modified + if - modified - since和ETag +具有。

  

if - modified - since last - modified +,单位是秒,这个容易理解,如果服务端资源的最后修改时间小于if - modified - since的值,表示资源无变动。与if - modified - since对应的有个If-Unmodified-Since,它类似一个断言,小于此时间戳的资源才返回,大于等于的话会返回412失败的前提错误。

  

使用时间戳校验有几个弊端:

  
      <李>文件有可能只改变修改时间,内容不变李   <李>文件在秒以下的时间修改无法判断李   <李>服务器可能不能精确获取文件的最后修改时间。   
  

因此,HTTP引入了ETag.ETag(实体标记)资源唯一标识,可看做服务端为资源生成的一个令牌,用于校验资源是否修改.北京只规定ETag要放在双引号内,没有规定内容是什么或者要怎么实现,Tomcat生成ETag的逻辑是

Tomcat中对静态资源的处理教程