Java Webstart 和 URLConnection caching API背景:

URLConnection 缓存 API 的描述是最后一句:

在 Java 2 标准版中没有 URLConnection 缓存的默认实现。但是,Java Plugin和Java WebStart确实提供了一个开箱即用的。

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

  • 哪些版本的 Webstart 在哪些平台上激活了缓存?
  • 在哪些情况下它处于活动状态?只有 HTTP Get?
  • 可以配置吗?
  • 源代码是否可用?

背景:

案例1

使用以下(时髦)代码

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,从而生成 .仅请求原始 url,从而导致 .所有后续执行都不涉及与服务器的任何通信。http://repo1.maven.org/maven2/.pack.gz404304 NOT MODIFIED

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

案例 2

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

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.<init>(Unknown Source)
    at java.util.zip.GZIPInputStream.<init>(Unknown Source)

有了两者,现在我无法重现问题。Java Web Start 1.6.0_24Java Web Start 10.2.1.255

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

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

由于缓存在我的机器上的webstart的稳定版本中似乎不活跃,我无法验证代码中是否再有错误,因此犹豫是否要提交错误报告。


答案 1

到目前为止,我找到的唯一信息是在JDK 7中的Java富Internet应用程序增强功能中

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

[...]

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


答案 2

我修改了您的代码。希望它对您有用。

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();