【问题标题】:Java - HttpUrlConnection returns cached response every timeJava - HttpUrlConnection 每次都返回缓存的响应
【发布时间】:2016-04-04 17:57:07
【问题描述】:

我正在尝试从 Roblox 的货币兑换处收集统计数据以进行分析。因此,我需要最新数据而不是缓存结果。但是,似乎无论我做什么,结果仍然被缓存。似乎最直观的选项setUseCaches() 没有效果,并且手动将标题设置为Cache-Control: no-cache 似乎也不起作用。我使用 Fiddler2 检查了缓存头,发现它的值为Cache-Control: max-age=0,但它似乎也没有改变程序的行为。以下是相关代码:

网址:

private final static String URL = "http://www.roblox.com/my/money.aspx#/#TradeCurrency_tab";

GET 请求:

    URLConnection socket = new URL( URL ).openConnection( );
    socket.setUseCaches( false );
    socket.setDefaultUseCaches( false );
    HttpURLConnection conn = ( HttpURLConnection )socket;
    conn.setUseCaches( false );
    conn.setDefaultUseCaches( false );
    conn.setRequestProperty( "Pragma",  "no-cache" );
    conn.setRequestProperty( "Expires",  "0" );
    conn.setRequestProperty( "Cookie", ".ROBLOSECURITY=" + ROBLOSECURITY );
    conn.setRequestProperty( "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" );
    conn.setRequestProperty( "Accept-Language", "en-US,en;q=0.8" );
    conn.setRequestProperty( "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36" );
    conn.setDoInput( true );
    conn.setRequestMethod( "GET" );
    conn.connect();

    Scanner data = new Scanner( conn.getInputStream() );
    data.useDelimiter( "\\A" );
    String result = data.next();

    data.close( );
    conn.disconnect();

请注意,每次我重新启动程序时它都会返回一个唯一的结果,而不是在程序运行时,这可能很重要,也可能不重要。

更新:

Wireshark 分析(自上次以来我稍微调整了代码):

GET /my/money.aspx HTTP/1.1
Pragma: no-cache
Expires: 0
Cookie: .ROBLOSECURITY=_|WARNING:-DO-NOT-SHARE-THIS.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items.|*sensitive*
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Cache-Control: no-cache
Host: www.roblox.com
Connection: keep-alive

HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Content-Type: text/html; charset=utf-8
Set-Cookie: rbx-ip=; domain=roblox.com; path=/; HttpOnly
Set-Cookie: RBXSource=rbx_acquisition_time=1/4/2016 12:45:21 AM&rbx_acquisition_referrer=&rbx_medium=Direct&rbx_source=&rbx_campaign=&rbx_adgroup=&rbx_keyword=&rbx_matchtype=&rbx_send_info=0; domain=roblox.com; expires=Wed, 03-Feb-2016 06:45:21 GMT; path=/
Access-Control-Allow-Credentials: true
Set-Cookie: rbx-ip=; domain=roblox.com; path=/; HttpOnly
Set-Cookie: RBXSource=rbx_acquisition_time=1/4/2016 12:45:21 AM&rbx_acquisition_referrer=&rbx_medium=Direct&rbx_source=&rbx_campaign=&rbx_adgroup=&rbx_keyword=&rbx_matchtype=&rbx_send_info=1; domain=roblox.com; expires=Wed, 03-Feb-2016 06:45:21 GMT; path=/
Set-Cookie: RBXEventTrackerV2=CreateDate=1/4/2016 12:45:21 AM&rbxid=59210735&browserid=3940274345; domain=roblox.com; expires=Fri, 22-May-2043 05:45:21 GMT; path=/
Set-Cookie: GuestData=UserID=-856460986; domain=.roblox.com; expires=Fri, 22-May-2043 05:45:21 GMT; path=/
P3P: CP="CAO DSP COR CURa ADMa DEVa OUR IND PHY ONL UNI COM NAV INT DEM PRE"
Date: Mon, 04 Jan 2016 06:45:20 GMT
Content-Length: 153751

【问题讨论】:

  • 你和互联网之间有代理吗?我以前因为代理缓存而遇到过问题。
  • 你能添加一个数据正确的whireshark日志和第二个不正确的比较吗?
  • Wireshark 转储通信的一个请求/响应周期是不够的。我们至少需要其中两个。另外,wireshark 是否在客户端主机上运行?
  • 您好,您有没有为此找到解决方案,我也遇到了同样的问题。

标签: java http caching httpurlconnection


【解决方案1】:

如果缓存发生在服务器端,则将 cachebuster 附加到 URL。

HttpURLConnection conn = ( HttpURLConnection )new URL( URL + "?_=" + System.currentTimeMillis() ).openConnection( );

【讨论】:

【解决方案2】:

我注意到你没有告诉本地 HttpURLConnection 绕过 它自己的缓存。

HttpURLConnectionURLConnection 继承方法setUseCaches(boolean)。来自Javadoc for setUseCaches(boolean)

将此 URLConnection 的 useCaches 字段的值设置为指定值。

有些协议会缓存文档。有时,重要的是能够“通过”并忽略缓存(例如,浏览器中的“重新加载”按钮)。如果连接上的 UseCaches 标志为真,则允许连接使用它可以使用的任何缓存。如果为 false,缓存将被忽略。默认值来自DefaultUseCaches,默认为true。

【讨论】:

  • 我已经尝试使用该方法无济于事。据我了解,它与使用“Cache-Control:no-cache”相同。
  • 您是否使用过 Wireshark 来确定您的系统是否正在发送请求?如果不是,则问题出在您的客户端。第一次和随后的流量交换会很有趣。
  • 那么第二次会发生什么?
  • 之后都一样了。
  • 你是通过代理吗? Wireshark 跟踪中的 content 是否也相同(即不正确)?您可以在服务器上运行网络捕获吗?
【解决方案3】:

您已经尝试了大部分缓存设置。可能不是您的客户,而是他们的服务导致这种情况发生。我可以从您的 wireshark 信息中看到您有“连接保持活动”。也许您可以尝试将其设置为“连接关闭”,因为您说每次重新启动程序时都会得到非缓存结果。

这在生产环境中可能并不理想,但也许它可以让您了解正在发生的事情。

【讨论】:

    【解决方案4】:

    我缺少上下文(如何多次调用给定的代码)来准确地确定问题,但这可能是由于重复使用 socket 对象而不是为每个请求实例化一个新对象。

    一旦连接打开,useCache 设置将不再重要。看看sun.net.www.protocol.http.HttpURLConnection#connect的实现:

    protected void plainConnect()  throws IOException {
      if (connected) {
            return;         
      }
      // try to see if request can be served from local cache
      if (cacheHandler != null && getUseCaches()) {
      // ..
    }
    

    如果连接已打开,它将立即返回并重用现有的InputStream 实例。

    【讨论】:

      【解决方案5】:

      您是否尝试过以下标头:

      Cache-Control: no-cache
      Pragma: no-cache
      If-Modified-Since: Sat, 1 Jan 2000 00:00:00 GMT
      

      【讨论】:

        【解决方案6】:

        我建议您在打开 URLConnection 套接字之前对您的 URL 执行以下操作:

        URLConnection socket = new URL( URL.replaceFirst("#", "?cacheFrom=" + System.currentTimeMillis()+"#") ).openConnection( );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-19
          • 2017-10-07
          • 2015-08-21
          • 2019-02-26
          • 2014-07-19
          • 1970-01-01
          相关资源
          最近更新 更多