URLConnection缓存API的描述为最后一句话:
Java 2 Standard Edition中没有URLConnection缓存的默认实现。然而,Java插件和Java WebStart确实提供了开箱即用的功能。
在哪里可以找到有关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
。所有后续执行都不涉及与服务器的任何通信。
我认为通过缓存功能透明地增强urlronnection的方法很好,有助于提高客户端应用程序的性能。但是,由于本例中的服务器既没有定义Expires标头,也没有定义缓存控制标头,我认为上面的代码应该始终询问服务器,而不是默默地忽略我的请求。
案例2
以下代码在使用webstart 10.1.1.255执行时不起作用(这是由java7的早期测试版安装的,但我不知道这是哪一个)
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_24
和现在的Java Web Start 10.2.1.255
,我无法重现这个问题。
在Wireshark中,我发现在出现错误的情况下,http标头包含一个If Modified Since条目,因此返回代码为304。在其他情况下,没有If Modified Since。因此,我认为缓存在稳定版本的webstart中是不活跃的——尽管上面的链接有最后一句话。
测试版的缓存似乎对http get请求进行了积极的调整:它确实使用了If Modified Since,并自动尝试使用gzip编码——即使客户端代码没有设置此标头。但是当缓存被命中时,返回的流不会被gzip,尽管getContentEncoding
返回"gzip"。
由于缓存在我机器上稳定版本的webstart中似乎不活跃,我无法再验证代码中是否存在漏洞,因此在提交漏洞报告时犹豫不决。
到目前为止,我发现的唯一信息是JDK 7 中的Java Rich Internet Applications Enhancements
默认情况下启用缓存:现在默认情况下已启用在Web启动模式下运行的应用程序代码的网络内容缓存。这允许应用程序提高性能,并与小程序执行模式保持一致。为了确保使用内容的最新副本,应用程序可以使用URLConnection.setUseCaches(false)或请求标头Cache Control值no-Cache/no-store。
[…]
使用gzip编码处理内容的改进:部署缓存将保持应用程序内容的压缩形式,并将其返回给应用程序,就像在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
我看不出有任何方法可以直接配置缓存。