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

这是我的代码:

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服务器。

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

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

如果您获得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],Last-Modified = [ 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]}

现在,使用与Last-Modified相同的值执行If-Modified-Since

 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”],日期= [Wed,2011年8月17日17:57:42 GMT],Last-Modified = [Wed,06 Oct 2010 02: 53:46 GMT],Connection = [keep-alive],Server = [nginx / 0.8.36],X-Cache = [HIT],Cache-Control = [max-age = 604800]}

现在,使用与ETag相同的值执行If-None-Match

 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],Last-Modified = [ 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被http://cdn3.sstatic后面的服务器完全忽略。网 。 这可能是(代理)配置问题或完全清楚地完成(不明显的原因imho)。

或者更短:)

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

 conn.setConnectionTimeout( 3000); 

在.openConnection()之后执行

 final HttpURLConnection conn = (HttpURLConnection) sourceURL.openConnection(); conn.setConnectionTimeout( 3000); 

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

 conn.setReadTimeout( 3000);