在工作生活中,我们会使用Tomcat中对静态资源处理,今天就给大家带来一些的相关资料,希望能对大家有所帮助。
资源缓存的设计
我们访问内存的速度远远高于访问磁盘的速度,为了让系统能够快速响应。我们需要适当的缓存一部分静态资源。
Tomcat 在 6.0.53 版本实现静态资源的处理时,借助了 JNDI 的一些 API。
缓存条目加入前会进行以下操作:
获取并初始化缓存资源属性
文件内容过小,那么将文件内容加载到内存中
检查是否过期,这需要分情况讨论
如果过期,再检查资源内容是否修改
如果修改,需要清除这个缓存,读取最新内容
HTTP/1.1 200 OK
资源缓存的设计
我们访问内存的速度远远高于访问磁盘的速度,为了让系统能够快速响应。我们需要适当的缓存一部分静态资源。
Tomcat 在 6.0.53 版本实现静态资源的处理时,借助了 JNDI 的一些 API,相关类图及核心方法和属性如下:
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"72259-1557127244000"
Last-Modified: Mon, 06 May 2019 07:20:44 GMT
Content-Type: text/css
Content-Length: 72259
Date: Mon, 06 May 2019 07:20:57 GMT
// 返回 true 是才认为资源有变动
protected boolean checkIfHeaders(HttpServletRequest request,
HttpServletResponse response,ResourceAttributes resourceAttributes)
throws IOException {
return checkIfMatch(request, response, resourceAttributes)
&& checkIfModifiedSince(request, response, resourceAttributes)
&& checkIfNoneMatch(request, response, resourceAttributes)
&& checkIfUnmodifiedSince(request, response, resourceAttributes);
}接下来由我为大家介绍关于Tomcat中对静态资源处理的相关资料,希望对大家学习或者使用Tomcat有一定的参考学习价值,有需求的铁子们下面来一起学习学习吧
首先:资源缓存的设计
通常情况瞎访问磁盘的速度往往要低于访问内存的速度,我们需要适当的缓存一部分静态资源使系统快速响应。
Tomcat 在 6.0.53 版本实现静态资源的处理时,借助了 JNDI 的一些 API,具体的方法和属性如下:
其次:缓存相关的类
ResourceCache: 实现很多功能,如资源查找、加载、销毁等功能
CacheEntry: 缓存一个条目或名称
资源目录相关的类是:
EmptyDirContext: 用于嵌入式模式
FileDirContext: 服务文件系统的资源目录
WARDirContext:服务 war 文件的目录
Resource: 封存资源内容
ResourceAttributes:指的是 资源属性
ProxyDirContext: 帮助你查找资源缓存、校验缓存是否过期等功能
一般情况下,我们使用 Mapper 映射处理静态资源的 Wrapper 时,会出现一些问题,简单的方法调用情况如下:
Mapper.map(MessageBytes, MessageBytes, MappingData)
└─Mapper.internalMap(CharChunk, CharChunk, MappingData)
└─Mapper.internalMapWrapper(Mapper$Context, CharChunk, MappingData)
└─ProxyDirContext.lookup(String)
└─ProxyDirContext.cacheLookup(String)
└─ResourceCache.lookup(String)
└─ResourceCache.find(CacheEntry[], String)
让缓存资源插入内部数组时是有规律的,一般有两种路径,此时有两种情况,缓存命中和未命中。
当缓存未命中时,在 cacheLookup 方法中会新建一个 CacheEntry 对象,调用 cacheLoad 方法加入到 ResourceCache 的缓存数组中,加入前要对缓存条目进行以下操作:
获取并初始化缓存资源属性文件的 contentLength 和 lastModified
如果文件长度过小,就将文件内容加载到内存中
我们需要标记缓存存在,并设置缓存时间戳
在缓存命中时,会对缓存条目进行校验:
检查是否过期,当前时间大于缓存条目设置的时间戳
如果过期,需要检查资源内容是否修改
如果修改,需要清除这个缓存,读取最新内容
那些缓存请求的资源会被客户端接受,,第二次请求此资源时,服务端根据特定的请求头域来验证资源是否修改,如果没有变动,就返回一个 304 Not Modified 响应,有被动的就返回资源的内容,节省带宽。
用于资源验证的头域有两种,
我们使用时间戳校验有一些弊端:
可能有的文件只改变修改时间,而内容不变
有的文件在秒以下的时间修改无法判断
服务器也许不能精确获取文件的最后修改时间。
所以,HTTP 引入了 ETag。ETag(Entity Tags) 资源唯一标识,可看做服务端为资源生成的一个 Token,用于校验资源是否修改。HTTP 只规定 ETag 要放在双引号内,没有规定内容是什么或者要怎么实现,Tomcat 生成 ETag 的逻辑是
"W/\"" + contentLength + "-" + lastModified + "\""
ETag+If-None-Match,If-None-Match 的值由 ETag 组成,ETag多了用逗号分割,如果服务端资源的 ETag 不匹配,表示请求的资源有修改;否则无变动。有一个特殊值-星号(*),只在资源上传时使用,通常是 PUT 方法,检查是否已经上传过。
If-None-Match 与If-Modified-Since相比优先级较高,存在 If-None-Match 就不对最后修改时间进行校验。
核心代码:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"72259-1557127244000"
Last-Modified: Mon, 06 May 2019 07:20:44 GMT
Content-Type: text/css
Content-Length: 72259
Date: Mon, 06 May 2019 07:20:57 GMT
我们就以请求 /main.css 静态资源为例,请求响应头信息如下:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"72259-1557127244000"
Last-Modified: Mon, 06 May 2019 07:20:44 GMT
Content-Type: text/css
Content-Length: 72259
Date: Mon, 06 May 2019 07:20:57 GMT
然后我们进行第二次请求时,需要看一下请求头域关键信息:
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost:8080
If-Modified-Since:Mon, 06 May 2019 07:20:44 GMT
If-None-Match:W/"72259-1557127244000"
当服务器匹配成功后,就表示资源没有修改,出现的情况如下
HTTP/1.1 304 Not Modified
Server: Apache-Coyote/1.1
ETag: W/"72259-1557127244000"
Date: Mon, 06 May 2019 07:21:46 GMT
需要注意的是
1.如果服务器设置了一个 Accept-Ranges: bytes 头,我们可以请求资源的一部分字节,当服务器发现有这个头时,就会尝试断点续传。
2.我们检查SendFile,NIO 模式能否支持此操作,也就是零拷贝,需要减少一次到应用内存的拷贝,直接从内核将数据写入通道。
原创文章,作者:网友投稿,如若转载,请注明出处:https://www.cloudads.cn/archives/4211.html