代码改变世界

web开发中的缓存问题的研究(三)

2006-05-15 12:38  java ee spring  阅读(225)  评论(0编辑  收藏  举报

web开发中的缓存问题的研究(一)
web开发中的缓存问题的研究(二)
web开发中的缓存问题的研究(三)

    (5)回到浏览器窗口中,简要记住一下浏览器窗口和Tomcat的命令行窗口中显示出的时间值,然后反复单击浏览器工具栏中的“后退”和“前进”按钮,可以看到每次显示出的CacheServlet页面内容都没有变化,Tomcat的命令行窗口中也没有打印出新的信息。直接在浏览器地址栏中输入CacheServlet的访问地址,结果也是如此。这说明用浏览器的“后退”或“前进”方式访问已缓存的页面时,或者直接在浏览器地址栏中访问已缓存的页面时,浏览器将直接调用缓存的内容,而不向服务器发出新的访问请求。
    在图4.18所示的Windows资源管理器窗口中删除CacheServlet页面的缓存文件,再次使用“后退”和“前进”按钮访问CacheServlet,或者直接在浏览器地址栏中输入CacheServlet的访问地址,这时候浏览器窗口和Tomcat的命令行窗口中都将显示出新的时间值。这说明,在缓存文件不再存在的情况下,使用“后退”和“前进”按钮访问CacheServlet时,或者直接在浏览器地址栏中输入CacheServlet的访问地址,浏览器将向服务器发出新的访问请求。
    通过浏览器工具栏中的“后退”或“前进”按钮回到CacheTest.html页面,然后单击其中的超链接来访问CacheServlet,这时可以看到浏览器窗口和Tomcat的命令行窗口中显示出了新的时间值。重复这个过程,可以看到CacheServlet页面每次都能显示出新的时间值,这说明通过其他网页文档中的超链接来调用CacheServlet时,浏览器将向服务器发出新的访问请求,而不是调用已缓存的内容。
    (6)修改CacheServlet.java源文件,取消对getLastModified方法的注释,重新编译CacheServlet.java源文件,等待Tomcat重新装载CacheServlet后,在浏览器窗口中刷新对CacheServlet的访问。打开Internet临时文件夹(如果该文件夹原来已经打开,则按F5键刷新一下),选中其中的CacheServlet缓存文件,从Windows资源管理器窗口中显示出的摘要信息中可以看到,这次的CacheServlet缓存文件中有了一个上次修改时间的记录信息,如图4.20所示。


图4.20

(7)重复第(4)步的操作,这时候的telnet窗口中显示出的结果如图4.21所示。


图4.21

    从图4.21中可以看到,CacheServlet这次返回的响应消息中多了一个Last-Modified头字段,这正是图4.20中显示的CacheServlet缓存文件有了一个上次修改时间的记录信息的原因。
    (8)回到浏览器窗口中,简要记住一下浏览器窗口和Tomcat的命令行窗口中显示出的时间值,然后反复单击浏览器工具栏中的“后退”和“前进”按钮,可以看到每次显示出的CacheServlet页面内容都没有变化,Tomcat的命令行窗口中也没有打印出新的信息。直接在浏览器地址栏中输入CacheServlet的访问地址,结果也是如此。这种情况与在步骤(5)中看到的实验效果完全一样。
    通过浏览器工具栏中的“后退”或“前进”按钮回到CacheTest.html页面,单击其中的超链接来访问CacheServlet,这时看到浏览器窗口和Tomcat的命令行窗口中显示出的内容仍然没有变化,多次重复这个过程,看到的结果还是没有变化。这种情况与步骤(5)中的看到的实验效果截然不同,通过两者的实验效果的对比,我们可以得出如下结论:

  • 如果某个页面的响应消息中包含有Last-Modified头字段,当通过其他网页文档中的超链接来调用这个页面时,浏览器只在每次启动后的第一次访问这个页面时才向服务器发出访问请求,对于在这次启动运行期间对该页面的后续访问,浏览器将不再向服务器发出访问请求,而是直接调用缓存的内容。在访问一个普通的HTML文件时,Tomcat的缺省Servlet都会产生一个Last-Modified头字段来说明这个HTML文件的最新修改时间,因此,在浏览器的一次启动运行期间,它只在对某个HTML文件进行第一次访问时才向服务器发出真正的访问请求。对HTML文件的页面来说,它的内容正好在某个浏览器的某次运行期间的对该页面的第一次和后续访问之间发生改变的概率很小,并且即使发生这种情况,也不会出现什么大的问题,所以,Tomcat的缺省Servlet的这种处理方式完全是合理的和应该的。
  • 如果某个页面的响应消息中没有包含Last-Modified头字段,当通过其他网页文档中的超链接来调用这个页面时,浏览器在整个启动运行期间对该页面的每次访问,都将向服务器发出访问请求,而不会调用已缓存的内容。因此,只要动态网页程序中没有产生Last-Modified头字段,就不用担心通过超链接再次访问该动态网页程序时会出现浏览器不向服务器发生访问请求的问题。

    在浏览器窗口中刷新对CacheServlet的访问,刷新的作用就是让浏览器务必向服务器发出访问请求,这时候浏览器窗口中显示出了新的内容。查看启动Tomcat的命令行窗口,可以看到其中打印出类似如下的两行新信息:
        getLastModified:1147408274473
        doGet:1147408274473
    这说明CacheServlet调用了getLastModified方法后,接着又调用了doGet方法。因为getLastModified方法返回的是当前时间,它肯定比浏览器发出的请求消息中的If-Modified-Since请求头字段指定的时间值(即getLastModified方法上次被调用时返回的“当前时间”)要新,所以,CacheServlet调用完getLastModified方法后,接着又调用了doGet方法,于是在浏览器中就看到了新的内容。
    (9)修改CacheServlet.java源文件,让getLastModified方法中的最后那条return语句返回一个固定的时间值,如下所示:
         protected long getLastModified(HttpServletRequest req)
                 {
                  long now = System.currentTimeMillis();
                  System.out.println("getLastModified:" + now);
                  return /*now*/1234;
                 }
    重新编译CacheServlet.java源文件,等待Tomcat重新装载CacheServlet后,新启动一个浏览器程序访问CacheTest.html页面,然后单击CacheTest.html页面中的“缓存测试”超链接访问CacheServlet,这时显示出来的CacheServlet页面的内容还是在步骤(8)中的最后看到的内容,没有发生改变!查看启动Tomcat的命令行窗口,可以看到其中仅打印出了一行类似如下的新信息:
        getLastModified:1147414361586
    这个现象说明,浏览器刚才确实向服务器发出了访问请求。由于浏览器发出的请求消息中带有一个If-Modified-Since请求头字段,其设置值为上次的Last-Modified头字段指定的时间,而CacheServlet中的getLastModified方法这次返回的时间值比Last-Modified头字段指定的时间值更旧(在一般情况下应该是相等,这里为了简化程序的编写,仅仅是返回1234这个比较陈旧的时间值,但不影响实验效果),所以,CacheServlet没有调用doGet方法(Tomcat的命令行窗口中没有打印出doGet方法被调用的提示信息),而是向浏览器返回一个304(Not Modified)状态码来表示浏览器缓存的版本是最新的,从而导致浏览器仍旧显示出了上次缓存的内容。
    在浏览器窗口中刷新对CacheServlet的访问,这时浏览器中显示的内容依然如故,查看启动Tomcat的命令行窗口,可以看到其中又只是打印出了一行getLastModified方法被调用的提示信息。可见,如果浏览器缓存的某个页面的响应消息中包含有Last-Modified头字段,当浏览器再次向服务器发出针对该页面的访问请求时,只要处理这个页面的Servlet程序的getLastModified方法返回的时间值比上次的Last-Modified头字段的时间值旧或者与之相同时,服务器就不会返回新的内容。
    (10)重复第(7)步的telnet访问操作,等待服务器返回响应结果后,接着输入如下内容:
         GET /it315/servlet/CacheServlet HTTP/1.1<回车>
         Host:<空格><回车>
         If-Modified-Since:<空格>Thu, 01 Jan 1970 00:00:01 GMT
         <回车>
    其中的If-Modified-Since头字段中的值是从刚才返回的Last-Modified头字段中进行复制得到的,这时候可以看到服务器只返回了一个304(Not Modified)状态码,而没有返回任何实体内容。接着输入如下内容:
         GET /it315/servlet/CacheServlet HTTP/1.1<回车>
         Host:<空格><回车>
         If-Modified-Since:<空格>Thu, 01 Jan 1970 00:00:00 GMT
         <回车>
    注意,其中的If-Modified-Since头字段中的值比上一次的值小了1秒,这时候可以看到服务器返回了200状态码和新的实体内容,如图4.22所示。


图4.22

web开发中的缓存问题的研究(一)
web开发中的缓存问题的研究(二)
web开发中的缓存问题的研究(三)