servlet 请求的资源未缓存 [重复]
Posted
技术标签:
【中文标题】servlet 请求的资源未缓存 [重复]【英文标题】:Resources requested by a servlet aren't cached [duplicate] 【发布时间】:2016-04-08 02:38:18 【问题描述】:我有一个 html 文件,可以通过浏览来访问
https://localhost:8080/contextRoot/home.html
此 html 使用 2 张图片:
<img src="https://localhost:8080/contextRoot/image1.jpg">
<img src="https://localhost:8080/static/images/image2.jpg">
第一个图像被打包在我的 war 文件中并且可以正常加载。当我重新加载页面时,它是从缓存中获取的,而不是重新下载它。我在浏览器的开发者工具中看到了这一点。
第二张图片也可以正常加载,但每次请求页面时都会下载。它永远不会被缓存。它使用一个特殊的 java servlet 来处理我们所说的静态内容:
<servlet>
<servlet-name>staticFileServlet</servlet-name>
<servlet-class>com.company.web.file.StaticFileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>staticFileServlet</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
此 servlet 在计算机磁盘上搜索文件夹 C://images/
以查找名为 image1
的文件,并通过将这些字节写入响应来提供它,同时还将内容类型标头指向响应(因此浏览器知道它正在接收的文件类型)。
我想我可能需要添加额外的标题来解释浏览器应该缓存这些内容。 Cache-control
标头可以在这里帮助我吗?但是,我认为浏览器足够聪明,可以缓存请求,无论我(不)使用什么标头。
这里是成功缓存的图像的响应标头(作为战争文件提供)
Accept-Ranges:bytes
Content-Length:354
Content-Type:image/gif
Date:Mon, 04 Jan 2016 09:43:42 GMT
ETag:W/"354-1449227028000"
Last-Modified:Fri, 04 Dec 2015 11:03:48 GMT
Server:Apache-Coyote/1.1
这是一个由 servlet 提供但未缓存的图像示例:
Cache-Control:max-age:864000
Content-Type:image/jpeg
Date:Mon, 04 Jan 2016 13:59:04 GMT
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
编辑:我的文件位于 SSL 连接后面,这可能导致缓存被拒绝。但是,我确定不是服务器拒绝此缓存,因为
-
它正在缓存一些图像。
响应中没有设置标头(pregma、etag、缓存控制...)。
谷歌浏览器会自动拒绝来自(某些)ssl 连接的缓存吗?
【问题讨论】:
打开您的开发者控制台,然后在清除缓存后重新加载页面,或者使用快捷方式刷新页面并忽略缓存(例如,Windows 上的 Chrome 是 CTRL+F5 或 SHIFT+CTRL+F5 )。对于这两个图像,请检查响应标头以查看是否有不同之处。 正在生成的图像具有标头 Last-Modified,而未缓存的图像则没有此标头。我在处理缓存控制、编译指示等的请求和响应中都没有看到任何标头。 我不知道正在使用哪个服务器(顺便提供的不是不重要的信息),但可能是它被配置为向 servlet 调用添加无缓存标头。 我正在使用 JBoss,它在后台使用 Apache-Coyote/1.1。当我使用 chrome 的开发人员工具时,我没有看到请求/响应中出现标题,如果 apache 自动添加它们,它们不应该在那里吗? 【参考方案1】:servlet 本身旨在以编程方式生成内容。因此,它通常期望的缓存行为不是缓存响应。但是,您可以控制缓存行为,方法是添加您提到的缓存控制标头,如果存在所需的请求标头,则在后续请求中提供 304 状态。由于可以动态创建具有不同内容的图像,因此这不是缓存行为的良好指标。另见:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
在一个地方实现这一点的好方法是使用过滤器,参见例如
https://github.com/samaxes/javaee-cache-filter
【讨论】:
我知道 servlet 可以提供动态内容,但我的 servlet 不能,而且我看不到网站如何知道它启动的更改/禁用缓存的请求发生了什么。我的缓存控制标头有问题,我似乎无法用它打开缓存,只能关闭它或限制缓存的持续时间? 你看过响应头了吗? 是的,我做到了。有效的图像有一个 ETAG 标头,但是我也有一个 gif 文件的示例,它的 etag 标头不起作用。我现在将 Cache-control 标头添加到不起作用的图像中,最大年龄为 3600*24(1 天)。我在浏览器的开发人员工具中看到了这个标题,所以它就在那里。唉,什么都没有发生,每次我请求给定的 html 页面时,图像仍然会重新加载。 请参阅github.com/samaxes/javaee-cache-filter/wiki/CacheFilter - 看起来它不仅与缓存控制标头有关,而且服务器还添加了 304 状态(我刚刚通过在 Chrome 上查看静态资源的标头验证了这一点)。这一切都可以通过使用指定的过滤器来实现。 我刚刚检查了cachefilter的源代码(在您提供的github链接上),我没有看到它在任何地方设置304状态。你能给我相关的行号,这样我就可以看到你在说什么代码?此外,成功缓存的图像和未缓存的图像在我的开发人员工具中的 http 状态均为 200(ok),所以我不确定 http 状态与此有什么关系?【参考方案2】:确保在您的响应中设置以下标头,以告知浏览器相同的后续请求应缓存 1 天:
Cache-Control:public, max-age=36000 内容类型:图片/jpeg 日期:周一, 格林威治标准时间 2016 年 1 月 4 日 14:56:52 到期时间:2016 年 1 月 5 日星期二 00:56:52 GMT您可以通过更改标头的值来更改缓存时间。
【讨论】:
以上是关于servlet 请求的资源未缓存 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Eclipse 中的 Servlet:请求的资源 [/Register/] 不可用 [重复]
超链接 `<a>` 未调用映射的 Servlet。返回 404:找不到资源 [重复]