我正在开发一个在 Struts2 和 Tomcat 7.0.42 上运行的 Web 应用程序。
我写了一个动态生成jsp文件的action,生成的.jsp,其中包含一些图像引用,并创建包含图像的关联“_files”文件夹。
该操作在另一个页面中调用,请求.html,通过JQuery ajax请求然后加载生成的.jsp带有 JQuery 负载。这请求.html文件看起来像这样:
<HTML>
<HEAD>
<script language="javascript">
$(function() {
$.ajax({
type: "POST",
url: "http://..../myAction.action",
data: someDataObj,
success: function(msg){
$("#myDiv").load("http://.../generated.jsp");
});
}
</script>
</HEAD>
<BODY>
<div id="myDiv"> </div>
</BODY>
</HTML>
每次请求时,该操作都会首先删除旧文件,然后生成所有内容。生成的图像取决于 ajax 请求中传递的数据。
The 生成的.jsp页面包含一些指令,使 tomcat 发送响应标头以防止页面被缓存:
<%
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
%>
如果我打开请求.html我不经常请求,在请求后等待几秒钟生成的显示页面后,一切都按预期工作:显示页面及其图像。
但是,如果我非常快地执行几个请求,例如每个请求等待不到一秒,我就会看到显示的图像是从旧请求生成的图像。
查看请求和响应标头,当它运行良好时,页面和图像的响应代码始终为“200 OK".
当问题发生时,tomcat 会响应 GET 请求生成的.jsp带有状态代码的页面“200 OK“,但是对其返回的图像的请求”304 未修改" 即使图像文件与上次请求的不同。
有请求/响应标头:
Request URL:http://.../generated.jsp
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:text/html, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,it;q=0.6
Connection:keep-alive
Cookie:JSESSIONID=44E591CE76423F14CCFBE2DF86F50DDE
Host:127.0.0.1:8080
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
X-Requested-With:XMLHttpRequest
Response Headersview source
Cache-Control:no-cache
Content-Type:text/html;charset=ISO-8859-1
Date:Tue, 03 Dec 2013 07:54:05 GMT
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Pragma:no-cache
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
Request URL:http://.../generated.jsp_files/img.png
Request Method:GET
Status Code:304 Not Modified
Request Headersview source
Accept:image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,it;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Cookie:JSESSIONID=300B5CB436CD60BA8E129B21B085A965
Host:127.0.0.1:8080
If-Modified-Since:Mon, 02 Dec 2013 15:31:57 GMT
If-None-Match:W/"1481-1385998317000"
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Response Headersview source
Date:Mon, 02 Dec 2013 15:32:00 GMT
ETag:W/"1481-1385998317000"
Server:Apache-Coyote/1.1
我不认为问题是由浏览器缓存引起的,因为请求完成,浏览器只有在收到304状态码后才使用缓存。
我尝试了不同的方法,直到找到解决方法。
首先,我修改了操作以在每次请求、页面和图像时删除旧文件,然后生成所有内容,但没有成功。
然后我尝试每次使用不同的名称生成图像,并将时间戳连接到文件名。
发生的事情是这样的生成的.jsp首先删除,然后在每次请求时参考新图像名称生成。
在这种情况下,当浏览器请求生成的.jsptomcat 返回页面200 OK状态码。当问题发生时,查看页面的来源,我可以看到返回的是带有old图像名称参考。
似乎 tomcat 无法识别文件更改,并且旧图像不再存在,因为在具有旧名称的图像的请求中,它仍然以304状态码。
看到这种行为,我检查 tomcat 工作目录以找到对应于的“java”和“class”文件生成的.jsp我发现这些文件的时间戳早于 webapp 文件夹中包含的页面。
此时我尝试了另一种解决方法:使操作删除 tomcat 的工作子文件夹,其中包含生成的.jsp相关文件。
即使这次尝试失败了,与接收旧版本的浏览器的行为相同生成的.jsp页面和图像的 304 状态代码。
唯一的解决方法是删除 webapp 文件夹中的旧页面并使用不同的名称创建页面,就像我对图像所做的那样。
我在文档中读到,Tomcat 会在每次请求时检查资源是否被修改,除非其中的某些属性web.xml被改变。
看到这种行为,我相信 tomcat 使用一些缓存来进行检查,并且不会每次都在文件系统上执行该检查,但我在文档中没有找到任何内容。
有人知道我是否错了,也许可以帮助我理解这些机制在 Tomcat 中是如何工作的?