Java 我可以跳过实现HttpEntity#getContent()吗?
我打算将结构化数据写入通过HTTP客户端访问的资源。用于执行此操作的API(用于JSON、YAML、XML)倾向于让我向他们传递一个Java 我可以跳过实现HttpEntity#getContent()吗?,java,apache-httpclient-4.x,Java,Apache Httpclient 4.x,我打算将结构化数据写入通过HTTP客户端访问的资源。用于执行此操作的API(用于JSON、YAML、XML)倾向于让我向他们传递一个OutputStream,他们将向其写入—他们不会给我一个InputStream 不管是好是坏,这里使用的客户端是ApacheHTTP组件HttpClient。(我们使用的其他库依赖于它。它在大多数情况下并不完全是坏的,至少不会迫使我们使用奇怪的线程本地黑客来获得正常的行为,不像java.net.URL) 发出请求时,HttpEntityEnclosingReque
OutputStream
,他们将向其写入—他们不会给我一个InputStream
不管是好是坏,这里使用的客户端是ApacheHTTP组件HttpClient。(我们使用的其他库依赖于它。它在大多数情况下并不完全是坏的,至少不会迫使我们使用奇怪的线程本地黑客来获得正常的行为,不像java.net.URL
)
发出请求时,HttpEntityEnclosingRequestBase
(在HttpClient中)强制我设置一个HttpEntity
,以将任何数据获取到服务器HttpEntity
似乎迫使我实现getContent()
,返回InputStream
我没有输入流
,因此我不得不在两种解决方法中进行选择:
A) 将所有数据序列化到内存中的字节数组中,然后再次将其流式输出。我不想这样做,因为通常情况下,数据的序列化形式比数据本身占用更多的内存,而且在某些情况下,我们甚至没有在内存中放在首位,所以这会带来麻烦
B) 创建一个管道
。旋转第二个线程,将对象写入管道的OutputStream
端。返回InputStream
end。这实际上不能在HttpEntity
本身中完成,因为HttpEntity
不知道何时不再需要数据流。(这可能是一个有根据的猜测,当你到达流的末尾时,它就完成了,但是如果到服务器的连接中途中断,你会让管道永远打开。)这意味着我最终会将解决方法移动到每个连接的地方,这是大量的结构重复
这两种解决方法都不是很好,但我想(B)是“不那么糟糕”,因为它至少不会在传输大型对象时使整个应用程序崩溃
就我所知:
public class WriteLogicEntity extends AbstractHttpEntity {
private final WriteLogic writeLogic;
public InputStreamEntity(WriteLogic writeLogic) {
this(instream, null);
}
public InputStreamEntity(WriteLogic writeLogic,
ContentType contentType) {
this.writeLogic = writeLogic;
if(contentType != null) {
this.setContentType(contentType.toString());
}
}
@Override
public boolean isRepeatable() {
// We could enforce that all WriteLogic be repeatable
// or add a similar method there, but at least for now,
// assuming it isn't repeatable is safe.
return false;
}
@Override
public long getContentLength() {
// We really don't know.
return -1L;
}
@Override
public InputStream getContent() throws IOException {
//TODO: What do we do here?
}
@Override
public void writeTo(OutputStream outstream) throws IOException {
writeLogic.withOutputStream(outstream);
}
@Override
public boolean isStreaming() {
return true; //TODO: Verify this choice
}
}
public interface WriteLogic {
void withOutputStream(OutputStream stream) throws IOException;
}
现在我想知道getContent()
是否可以抛出UnsupportedOperationException。当然,在发出请求时,他们无论如何都会使用writeTo()
,对吗?嗯,我想不出来。即使它在一个实验中有效,也不能保证某种请求不可能要求调用getContent()
所以我想知道是否有比我更了解这个库的人可以调用它-跳过实现这个方法安全吗
(这个
getContent()
方法似乎不应该出现在API中。或者应该对它进行记录,至少让我有办法实现它。无论如何,我打算对它提出一个bug,因为在您尝试编写请求时,强制提供InputStream
非常不方便。)如果实体内容不能表示为InputStreamgetContent
方法可以抛出UnsupportedOperationException。HttpClient内部使用writeTo
将实体内容流式输出到底层HTTP连接。我认为可以安全地假设您的请求实体不会调用getContent方法,这正是这个问题所建议的-。我想如果你真的想确定的话,你可以问一下hc邮件列表。难道你不知道呼叫者什么时候关闭了InputStream
吗?@immibis他们为什么要关闭它?我打开了它,所以它是属于我的。@stringy05该死,它看起来像是我复制的。我也非常努力地搜索…@Trejkaz调用getInputStream
的人会关闭返回的流。