http304状态码缓存设置问题

时间:2021-01-18 15:27:32
当浏览器第一次加载资源的时候,返回一般为200,意思是成功获取资源,并会在浏览器的缓存中记录下max-age,第二次访问的时候:
如果只是用浏览器打开,那么浏览器会去判断这个资源在缓存里有没有,如果有的话,会去判断max-age,看看过期没有,如果没有过期,则直接读缓存,根本不会和服务器进行交互,换句话说,断网都能打开,就和本地跑一样!如果已经过期了,那就去服务器请求,等待服务器响应,这是很费时间的,服务器如果发现资源没有改变过,那么就会返回304,告诉浏览器,我没变过,你去读缓存吧,于是浏览器也不用从服务器拉数据了,然而,等待服务器响应也是一个很要命的问题,在网速发达的今天,等一个响应,有时比下载还慢。
如果是用浏览器刷新的,那么浏览器不会去判断max-age了,直接去服务器拿,如果服务器判断资源没变过,则还是会返回304,和上面是一样的,所以刷新一下,其实很可怕,等于把所有的资源都要去服务器请求一边,问问服务器我过期了没有。
综上,尽量减少网页的资源数量!尽量合并JS CSS 图片!响应速度将会猛增!

3xx (重定向) 
要完成请求,需要进一步操作。通常,这些状态码用来重定向。Google 建议您在每次请求中使用重定向不要超过 5 次。您可以使用网站管理员工具查看一下 Googlebot 在抓取重定向网页时是否遇到问题。诊断下的网络抓取页列出了由于重定向错误导致 Googlebot 无法抓取的网址。

300(多种选择) 针对请求,服务器可执行多种操作。服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301(永久移动) 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。您应使用此代码告诉 Googlebot 某个网页或网站已永久移动到新位置。
302(临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来响应以后的请求。此代码与响应 GET 和 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置,但您不应使用此代码来告诉 Googlebot 某个网页或网站已经移动,因为 Googlebot 会继续抓取原有位置并编制索引。
303(查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。对于除 HEAD 之外的所有请求,服务器会自动转到其他位置。
304(未修改)

自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。

如果网页自请求者上次请求后再也没有更改过,您应将服务器配置为返回此响应(称为 If-Modified-Since HTTP 标头)。服务器可以告诉 Googlebot 自从上次抓取后网页没有变更,进而节省带宽和开销。

.

305(使用代理) 请求者只能使用代理访问请求的网页。如果服务器返回此响应,还表示请求者应使用代理。
307(临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来响应以后的请求。此代码与响应 GET 和 HEAD 请求的 <a href=answer.py?answer=>301</a> 代码类似,会自动将请求者转到不同的位置,但您不应使用此代码来告诉 Googlebot 某个页面或网站已经移动,因为 Googlebot 会继续抓取原有位置并编制索引。
 
  打算将cache-control的各个值都试一遍,看看最终效果是否和预期一致。 
   先尝试max-age。其作用是:假如请求了服务器并在a时刻返回响应结果,则在max-age规定的秒数内,浏览器将不会发送对应的请求到服务器,数据由缓存直接返回;超过这一时间段才进一步由服务器决定是返回新数据还是仍由缓存提供。 
   设置max-age的方式是tomcat的filter。
Java代码  http304状态码缓存设置问题
  1. package itims;
  2. public class TestHTTP implements Filter{
  3. private static transient Log logger = LogFactory.getLog(TestHTTP.class);
  4. @Override
  5. public void destroy() {
  6. }
  7. @Override
  8. public void doFilter(ServletRequest servletrequest,
  9. ServletResponse servletresponse, FilterChain filterchain)
  10. throws IOException, ServletException {
  11. filterchain.doFilter(servletrequest, servletresponse);
  12. if (servletrequest instanceof HttpServletRequest && servletresponse instanceof HttpServletResponse) {
  13. HttpServletRequest request = (HttpServletRequest) servletrequest;
  14. HttpServletResponse response = (HttpServletResponse) servletresponse;
  15. logger.info("request.getRequestURI:"+request.getRequestURI());
  16. response.setHeader("Cache-Control", "max-age=" + cacheTime);
  17. }
  18. }
  19. @Override
  20. public void init(FilterConfig arg0) throws ServletException {
  21. }
  22. }

web.xml,只针对js和css文件进行设置。

Xml代码  http304状态码缓存设置问题
  1. <filter>
  2. <filter-name>cache-filter</filter-name>
  3. <filter-class>itims.TestHTTP</filter-class>
  4. <init-param>
  5. <param-name>cache-time</param-name>
  6. <param-value>30</param-value>
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>cache-filter</filter-name>
  11. <url-pattern>*.js</url-pattern>
  12. </filter-mapping>
  13. <filter-mapping>
  14. <filter-name>cache-filter</filter-name>
  15. <url-pattern>*.css</url-pattern>
  16. </filter-mapping>

httpTest.jsp

Html代码  http304状态码缓存设置问题
  1. <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  2. pageEncoding="ISO-8859-1"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <%
  5. String path = (String) request.getContextPath();
  6. %>
  7. <html>
  8. <head>
  9. <!--
  10. <meta http-equiv="refresh" content="5;url=http://localhost:8088/itims/testRRD.action">
  11. -->
  12. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
  13. <script type="text/javascript" src="<%=path%>/widget/jquery/jquery-1.3.2.min.js"></script>
  14. <title>httpTest</title>
  15. </head>
  16. <body>
  17. <p>
  18. success!
  19. </p>
  20. </body>
  21. </html>

在浏览器内输入httpTest.jsp,则抓取的请求/响应信息如下:

Java代码  http304状态码缓存设置问题
  1. http://localhost:8088/itims/widget/jquery/jquery-1.3.2.min.js
  2. GET /itims/widget/jquery/jquery-1.3.2.min.js HTTP/1.1
  3. Host: localhost:8088
  4. User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:6.0) Gecko/20100101 Firefox/6.0
  5. Accept: */*
  6. Accept-Language: zh-cn,zh;q=0.5
  7. Accept-Encoding: gzip, deflate
  8. Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
  9. Connection: keep-alive
  10. Referer: http://localhost:8088/itims/springTest.jsp
  11. Cookie: JSESSIONID=4B83B20F13BBCD37D1C0FB406807FA75
  12. If-Modified-Since: Sun, 28 Aug 2011 13:06:44 GMT
  13. If-None-Match: W/"57254-1314536804640"
  14. HTTP/1.1 304 Not Modified
  15. Server: Apache-Coyote/1.1
  16. Etag: W/"57254-1314536804640"
  17. Cache-Control: max-age=30
  18. Date: Sun, 28 Aug 2011 13:19:35 GMT

jquery-1.3.2.min.js的max-age被设置为30秒。即30秒内,无论用户在浏览器地址栏上敲多少次回车,后台也不应该打印日志,而我这个信息抓取工具也不应该抓取到任何信息。事实的确如此。注意,不同的操作方式影响最终结果,原因是刷新和强制刷新会额外发送cache-control信息。 
f5或刷新按钮:cache-control:max-age=0 
ctrl+f5:cache-control:no-cache 
        pragma:no-cache 
疑难杂症: 
1、为什么把缓存清干净并访问页面后,再次通过按回车访问页面时,浏览器却不再发送请求了,而按f5又可以? 
   答:观察响应信息可知,把缓存清干净后cache-control的设置消失了,原因不明。如果按回车,则此时缓存永远都起作用,自然不用访问服务器;而按f5则是强制访问,且此时cache-control的设置又能出现,所以之后所有的访问都遵循cache-control的设置。