Java Webstart和URLConnection缓存API

URLConnection缓存API的描述表示为最后一句:

Java 2 Standard Edition中没有URLConnection缓存的默认实现。 但是,Java插件和Java WebStart确实提供了一个开箱即用的function。

在哪里可以找到有关Webstart ResponseCache的更多信息?

  • Webstart的哪些版本在哪些平台上激活缓存?
  • 它在哪些情况下是活跃的? 只有HTTP获取?
  • 可以配置吗?
  • 源代码是否可用?

背景:

情况1

使用以下(groovy)代码

def url = new URL('http://repo1.maven.org/maven2/') def connection = url.openConnection() def result = connection.inputStream.text 

我希望每次执行代码时都会联系服务器。 但是当执行时

 Java Web Start 10.9.2.05 JRE-Version verwenden 1.7.0_09-b05 Java HotSpot(TM) Client VM 

行为是不同的。 第一次执行代码时,会联系服务器。 代码的所有后续执行都不涉及与服务器的任何通信(使用wireshark跟踪)。

但它变得更加奇怪。 重新启动webstart应用程序后,第一次执行代码时,请求URL为http://repo1.maven.org/maven2/.pack.gz ,结果为404 。 仅请求原始url导致304 NOT MODIFIED 。 所有后续执行都不涉及与服务器的任何通信。

我认为使用缓存function透明地增强urlconnection的方法很好,很好,有助于提高客户端应用程序的性能。 但由于在这种情况下服务器没有定义Expires头,也没有定义缓存控制头,我认为上面的代码应该始终询问服务器而不是默默地忽略我的请求。

案例2

以下代码在使用webstart 10.1.1.255执行时不起作用(这是由java 7的早期测试版安装的,但我不知道这是哪一个)

 URL url = new URL("http://repo1.maven.org/maven2/"); URLConnection connection = url.openConnection(); connection.setRequestProperty("Accept-Encoding", "gzip"); connection.connect(); InputStream is = connection.getInputStream(); if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) { is = new GZIPInputStream(is); } is.close(); 

使用Java Web Start 10.1.1.255从第二次执行开始,我得到了一个

 java.io.IOException: Not in GZIP format at java.util.zip.GZIPInputStream.readHeader(Unknown Source) at java.util.zip.GZIPInputStream.(Unknown Source) at java.util.zip.GZIPInputStream.(Unknown Source) 

使用Java Web Start 1.6.0_24和现在的Java Web Start 10.2.1.255我无法重现该问题。

使用Wireshark,我看到在我收到错误的情况下,http头包含一个If-Modified-Since条目,因此返回码是304.在其他情况下,没有If-Modified-Since。 因此,我认为在webstart的稳定版本中缓存并不活跃 – 尽管上面链接的最后一句话。

看来,测试版的缓存会对http获取请求进行积极的调整:它确实使用了If-Modified-Since并自动尝试使用gzip编码 – 即使客户端代码没有设置此标头。 但是当高速缓存被命中时,返回的流不会被gzip压缩,尽管getContentEncoding返回“gzip”。

由于缓存在我的机器上的稳定版webstart中似乎没有活动,我无法再validation错误是否在代码中,因此不愿提交错误报告。

到目前为止,我发现的唯一信息是JDK 7中的Java Rich Internet Applications增强function

默认情况下启用缓存:默认情况下,现在启用在Web启动模式下运行的应用程序代码的网络内容缓存。 这允许应用程序改进性能并与applet执行模式保持一致。 为确保使用最新的内容副本,应用程序可以使用URLConnection.setUseCaches(false)或请求标头Cache-Control值no-cache / no-store。

[…]

使用gzip编码处理内容的改进:部署缓存将应用程序内容保持为压缩forms,并按照HTTP标头中的gzip内容编码将其返回到应用程序。 这使得行为在不同的执行模式下更加一致(首次启动与后续启动,启用缓存与禁用缓存)。 有关详细信息,请参阅6575586 。

我修改了你的代码。 希望对你有效。

 URL url = new URL("http://repo1.maven.org/maven2/"); URLConnection connection = url.openConnection(); connection.setRequestProperty("Accept-Encoding", "ISO-8859-1"); connection.connect(); InputStream is = connection.getInputStream(); if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) { is = new GZIPInputStream(is); } is.close(); 

缓存似乎由com.sun.deploy.cache.DeployCacheHandler实现,它位于deploy.jar中。 我找不到任何官方资料库的来源; 这个链接是某种灰色市场的副本。

我一眼就看不到任何迹象表明它在任何特定平台上被禁用(或启用!)。 至少从Java 6开始,这个缓存处理程序已经存在。

它只缓存GET请求。 isResourceCacheable方法中的注释说明:

  // do not cache resource if: // 1. cache disabled // 2. useCaches is set to false and resource is non jar/zip file // 3. connection is not a GET request // 4. cache-control header is set to no-store // 5. lastModified and expiration not set // 6. resource is a partial body resource 

我没有看到任何直接配置缓存的方法。