在使用基于PL/SQL的web应用程序时,mod_plsql的一个非常令人烦恼的方面是当你在数据库外使用图片时,你的浏览器似乎从不对它们进行缓存。使用过Cache-Control、Expires和Last-Modified头,但是似乎都不起作用。每一次重新加载页面时,浏览器就会重新加载所有从mod_plsql而来的图片,但是它会将从文件系统而来的图片从缓存中获得。这使得对于终端用户来说如果页面拥有大量图片的话页面会显得非常缓慢,而这些图片是可以被缓存的。
对于要使用大量存储在数据库中图片的项目来说,要解决这个缓存问题,可以使用Java将这些图片写到文件系统上,这样Apache就可以以被缓存的方式来使用它们了。在这么做之前,先使用Firebug和Wireshark来作些跟踪。关于这些工具有些事要注意。当使用Firebug>Net>Images来跟踪图片缓存时,一个浅灰色条显示一个缓存的图片而一个深灰色条显示非缓存图片。当使用wireshark时,右键单击相应的捕获包,例如一个图片的Get,然后选择“FollowT CP Stream”。这会按顺序显示给你这个包流。
我从跟踪Apache的一个静态页开始,它包含一些从文件系统而来的图片。我发现每一次重新加载页面的时候,浏览器都会重新提交相同的“Get”请求,当我按shift+refresh或是简单地刷新时,会相应地返回一个非缓存页面或缓存页面。一个问题是“If-Modified-Since”和“If-None-Match”头只在缓存页面上,不过我将采用缓存页面。所以,浏览器每次都请求图片(或文件),这意味着它不会缓存这些图片。所以,我是在服务器端丢了些东西。
下面的例子是Firefox和Apache之间的一个虚拟对话:
Firefox:获得logo.gif?http://www.xvna.com
Apache:HTTP200“OK”了, Etag:ABC123,Content-Length: 35, gif文件内容
Firefox:Get logo.gif?http://www.xvna.com,If-None-Match:ABC123
Apache:HTTP304“Not Modified”, Etag:ABC123,Content-Length:35, 头关闭了,没有文件返回
对于第一个对logo.gif?http://www.xvna.com的请求,Apache返回了一个Etag头和这个文件的内容。对于第二个请求,Firefox发送了Etag的值作为If-None-Match头。Apache比较了这些值并简单地返回了一个304状态,而不是图片,因为值是一样的。
什么是ETag?它是一个用于某个文件的唯一标识符,文件改变时它也要改变。它的相应请求头是“If-None-Match”。可以在“Last-Modified”响应头和“If-Modified-Since”请求头之间做相同的对比。HTTP规范认为Etag是一个“强”属性而“Last-Modified”是一个“弱”属性,所以我在这里将关注于Etag。
所以,以前我们一直希望Apache或mod_plsql能够缓存我们的图片,但实际上我们(PL/SQL程序员)是要做这个缓存的人。不过幸好它很简单,特别是现在你已了解了这个问题。
为了使其起作用,你需要做3件事:
使If-None-Match CGI环境变量可用于mod_plsq或内嵌网关。
将包含所有图片请求的Etag头发送回去。
当有一个图片请求时,比较Etag和If-None-Match头,返回一个304 Not Modified头或者返回这个图片。
如果你使用内嵌的PL/SQL网关,那么以SYS权限执行下面的代码添加2个CGI环境变量: