当使用 Jersey 将大文件作为 InputStream 放置时客户端,似乎文件的全部内容在发送到服务器之前被缓冲到内存中。当 JVM 耗尽堆空间时,这会导致大文件出现问题。如何在 Jersey 客户端中防止这种行为?服务器端的JAX-RS资源方法在发送数据时似乎没有这个问题。
例如:
WebResource dataUploadResource = buildDataUploadResource();
dataUploadResource.type(getMimeType()).put(getLargeInputStream());
最佳答案
为了防止这种行为,您需要将 Jersey 客户端配置为使用分 block 编码 1对于请求。这消除了设置 Content-Length header 的需要,并且将从提供的 InputStream 流式传输,而无需在内存中缓冲整个内容。
默认情况下,Jersey 使用 JDK 的 HttpURLConection 类来处理 HTTP 请求和响应。不幸的是,这有一些与分 block 编码传输相关的错误。幸运的是,Jersey 具有允许使用不同 HTTP 客户端实现的扩展点。一种这样的实现是基于 Apache Http 客户端 2 .
存在两种 apache htpp 客户端处理程序的实现,一种支持现已停产的 3.x 版本,另一种使用较新的 4.x 版本。对于我们的项目,我们使用了基于旧 (3.1) 版本的实现。该库位于 Maven Central 的“贡献”子组下。
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-apache-client</artifactId>
<version>1.14</version>
</dependency>
接下来您必须初始化 Jersey 客户端以使用新的实现:
Client jerseyClient = ApacheHttpClient.create(getClientConfig());
为了启用分 block 编码,您必须在客户端配置中设置分 block 编码大小,因为它默认情况下未启用:
private ClientConfig getClientConfig() {
ClientConfig config = new DefaultClientConfig();
config.getProperties().put(
DefaultApacheHttpClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 0);
return config;
}
只要此属性不是null
,就会使用分 block 编码。事实上,1.14 版忽略了编码大小,因为底层 apache commons-httpclient 库不支持指定大小。
关于java - 防止 Jersey 客户端在发布大文件时导致内存不足错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11176824/