我正在尝试使用Java的HttpURLConnection来执行“条件获取”,但我从未获得304状态代码

时间:2011-08-17 15:59:56

标签: java http caching http-caching

这是我的代码:

    final HttpURLConnection conn = (HttpURLConnection) sourceURL.openConnection();
    if (cachedPage != null) {
        if (cachedPage.eTag != null) {
            conn.setRequestProperty("If-None-Match", cachedPage.eTag);
        }
        conn.setIfModifiedSince(cachedPage.pageLastModified);
    }

    conn.connect();

    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {

        newCachedPage.eTag = conn.getHeaderField("ETag");
        newCachedPage.pageLastModified = conn.getHeaderFieldDate("Last-Modified", 0);

    } else if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
        // Never reaches here
    }

我似乎永远不会得到HTTP_NOT_MODIFIED响应代码,甚至连续多次点击同一个服务器 - 页面肯定没有变化。此外,conn.getHeaderField(“ETag”)似乎总是响应null,有时conn.getHeaderFieldDate(“Last-Modified”,0)返回0.我已经尝试过针对各种Web服务器。

谁能告诉我我做错了什么?

2 个答案:

答案 0 :(得分:17)

你们都依赖于服务器配置。

如果您收到Expires响应标头,则表示您在指定的过期时间之前不需要请求任何内容。如果您获得Last-Modified响应标头,则表示您应该能够使用If-Modified-Since进行测试。如果您收到ETag响应标头,则表示您应该能够使用If-None-Match进行测试。

http://cdn3.sstatic.net/stackoverflow/img/favicon.ico为例(Stackoverflow的favicon图像):

URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
System.out.println(connection.getHeaderFields());

这给出了:

  

{null = [HTTP / 1.1 200 OK],ETag = [“9d9bd8b1165cb1:0”],日期= [星期三,2011年8月17日17:57:07 GMT],Content-Length = [1150],最后 - 修改= [Wed,2010年10月6日02:53:46 GMT],Content-Type = [image / x-icon],Connection = [keep-alive],Accept-Ranges = [bytes],Server = [nginx / 0.8 .36],X-Cache = [HIT],Cache-Control = [max-age = 604800]}

现在,执行与If-Modified-Since具有相同值的Last-Modified

URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
connection.setRequestProperty("If-Modified-Since", "Wed, 06 Oct 2010 02:53:46 GMT");
System.out.println(connection.getHeaderFields());

这给出了预期的304:

  

{null = [HTTP / 1.1 304未修改],ETag = [“9d9bd8b1165cb1:0”],日期= [星期三,2011年8月17日17:57:42 GMT],最后修改= [星期三,10月6日2010 02:53:46 GMT],Connection = [keep-alive],Server = [nginx / 0.8.36],X-Cache = [HIT],Cache-Control = [max-age = 604800]}

现在,执行与If-None-Match具有相同值的ETag

URLConnection connection = new URL("http://cdn3.sstatic.net/stackoverflow/img/favicon.ico").openConnection();
connection.setRequestProperty("If-None-Match", "9d9bd8b1165cb1:0");
System.out.println(connection.getHeaderFields());

这意外地 200:

  

{null = [HTTP / 1.1 200 OK],ETag = [“9d9bd8b1165cb1:0”],日期= [星期三,2011年8月17日18:01:42 GMT],Content-Length = [1150],最后 - 修改= [Wed,2010年10月6日02:53:46 GMT],Content-Type = [image / x-icon],Connection = [keep-alive],Accept-Ranges = [bytes],Server = [nginx / 0.8 .36],X-Cache = [HIT],Cache-Control = [max-age = 604800]}

更令人惊讶的是,当两个标头都设置为随机垃圾值为ETag时,服务器仍然提供304.这表明If-None-Match被{{1}}完全忽略后面的服务器{ {3}}。这可能是(代理)配置问题或完全明确地完成(不是出于明显的原因imho)。

答案 1 :(得分:-4)

或更短:)

尝试设置0以外的连接超时

conn.setConnectionTimeout( 3000);

在.openConnection()

之后执行
final HttpURLConnection conn = (HttpURLConnection) sourceURL.openConnection();
conn.setConnectionTimeout( 3000);

如果没有设置readTimeout而不是0。

conn.setReadTimeout( 3000);