asp.net页面的304 Not Modified代码与 原理

通过前面的示例,我们已经看到缓存带来的好处:那就是可以减少到服务器的访问,由于不访问服务器就能显示页面,这对于服务器来说, 能减轻一定的访问压力。但是,如果用户强制刷新浏览器,那么浏览器将会忽略缓存页,直接向服务器重新发起请求。

也就是说:缓存页在用户强制刷新浏览器时会无效。
但是,我们之所以使用缓存页,是因为我们希望告诉浏览器:这些数据在一定时间内,并不会发生变化,因此根本不需要再次请求服务器了。 然而,我们不能阻止用户的行为。由于浏览器的重新访问,我们原来设想的缓存想法将会落空,最后的结果是: 页面在服务器中重新执行,产生的HTML代码将重新发送到客户端。而这一重新刷新的结果可能也是无意义的,因为数据可能根本没有发生变化, 因此得到的页面也是不可能有变化的。

再来举个简单的例子来说吧:客户端要浏览一张图片。 当浏览器第一次要访问图片时,浏览器肯定是没有它的任何缓存记录的,此时它去访问服务器,服务器也返回图片的内容了。 但由于图片可能会被多个页面所引用,而它被修改的可能性是很小的。 因此没有必要为同一浏览器的多次请求都去读取图片并返回图片的内容,这样做既影响性能也学浪费带宽。 于是,像IIS这样服务器软件针对这类静态文件的访问时,都会在响应头上输出一些标记,用来告之浏览器这个文件你可以缓存起来了。

还是回到前面所说的【用户强制刷新】问题,此时的IIS又会如何处理呢?请看下图:

注意哦,此时除了HTTP状态码变成304之外,没有任何数据返回哦。

为了让您对304应答有个深刻的印象,我截了一张状态码为200的图片响应结果:

通过这二张图片的对比,现在看清楚了吧:304和200并不只是数字上的差别,最重要的差别在于有没有返回结果。

没有返回结果,浏览器该如何显示?
您会有这样的疑虑吗?
其实不用担心,此时浏览器会使用它缓存版本来显示。也就是说:不管用户如何强制刷,服务器就是不返回结果,但仍然可以正常显示。

显然,这个效果就是我们想要的。
前面所说的缓存页遭用户强刷的问题,如果采用这种方法,就比较完美了。
不过,有一点我要提醒您:Visual Studio自带的那个WebDev.WebServer.exe不支持304应答,所以您就不要拿它试验了,不会有结果的。

如何编程实现304应答

前面我们看到了304应答的效果。不过,在ASP.NET中,我们开发的程序,是动态页面,而不是图片, 我们更希望某个页面能以这种方式缓存一段时间,我想这个需求或许会更有意义。

下面,我就来演示如何通过编程的方式实现它。
接下来的示例中,页面的显示还是那个样,显示页面在服务器上产生的时间,时间变化了,说明页面被重新执行了。

重新截一系列的图片,我认为意义也不大,我就截一张图片展现多次强刷而产生的过程

上图反映了我多次请求某个ASPX页面的过程,从图片中可以看出,只有第一次是200的响应,后面全是304,是您所期待的结果吧。

再来看看它的实现代码吧: 

虽然代码并不复杂,但我还是打算来解释一下:
在浏览器第一次请求页面时,会执行SetLastModified的调用,它会在响应时输出一个"Last-Modified"这个响应头, 然后,当浏览器再次访问这个页面时,会将上次请求所获取的"Last-Modified"头的内容 , 以"If-Modified-Since"这个请求头的形式发给服务端,此时服务器就可以根据具体逻辑来判断要不要使用304应答了。

在前面的请求图片的示例中,服务器以图片文件的最后修改时间做为"Last-Modified"发给浏览器, 浏览器在后续请求那张图片时,又以"If-Modified-Since"的形式告之服务端,此时服务端只要再次检查一下这张图片就知道图片在上次访问后有没有发生修改, 如果没有修改,当然就以304的形式告之浏览器:继续使用缓存版本。

还是前面的请求图片的示例,其实服务端还使用了另一对【请求/响应】头:

这二个头的使用方式是:服务端输出一个ETag头,浏览器在接收后,以If-None-Match的形式在后续请求中发送到服务端, 供服务端判断是否使用304应答。

"Last-Modified"与"ETag"这二者,事实上只需要使用一个就够了,关键还是看服务端如何处理它们,浏览器只是在接收后,下次再发出去而已。

不过,前面的示例代码并没有使用缓存头,事实上,也可以带上它,这样可以尽量减少对服务器的访问,毕竟用户不会一直强刷浏览器。 这二种方式虽然有较大差别,但它们绝对是可以互补的。

为了能形象的描绘缓存页(或者其它文档)的请求过程,我画了张示意图供大家参考:

如何避开HTTP缓存

前面小节中,介绍了二种方法使用浏览器的缓存。但有些时候可能反而希望浏览器能放弃它缓存的结果。 现在的浏览器都有缓存功能,尤其是对一些静态文件,比如:图片,JS,CSS, HTML文件,都能缓存。 但有时候我们需要更新CSS, JS文件呢,浏览器如果还使用它的缓存版本,显然就有问题了。 而且有些网站使用了URL重写,使原来的动态页面扩展名也变成静态的HTML文件了, 因此,仍然希望浏览器在某些时候能够不要缓存这些伪静态页面。

此时,我们就希望浏览器放弃从HTTP请求所获得的结果了。 一般说来,浏览器在处理(它认为的)静态文件时,会按照URL为kEY来保存那些缓存结果, 因此,通常的解决办法也就是修改URL,比如:原来是请求abc.js的,要改成abc.js?t=23434,后面要跟上一个参数, 让以前的缓存不起作用。至于参数t的取值可以根据文件的最后修改时间,也可以手工指定,总之只要改变它就可以了。

但是,对于伪静态的页面,我们不能再使用这种方法了,原因就不用解释了吧。
那么,可以采用在服务端输出一个响应头,通过响应头的方式告之浏览器,不要缓存此文件。 比如,可以调用这个方法:

Response.Cache.SetNoStore();

它会生成这样的响应头内容:

Cache-Control: private, no-store

许多浏览器都能识别它。还有另一种方法是设置一个已过期的过期时间。

前面所说的在URL中加额外参数的做法,在JS中也比较常用,比如 JQuery就支持让某个Ajax请求不缓存, 它的方式就是设置{cache: false},最终它便会在生成的URL中加上一个临时参数,以保证后面的请求的地址是不重复的, 最终达到避开缓存的目的。JQuery的使用太简单,我就不再给出示例代码了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值