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

在工作生活中,我们会使用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

发表评论

登录后才能评论