Java 我可以跳过实现HttpEntity#getContent()吗?

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

我打算将结构化数据写入通过HTTP客户端访问的资源。用于执行此操作的API(用于JSON、YAML、XML)倾向于让我向他们传递一个
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
非常不方便。)

如果实体内容不能表示为InputStream
getContent
方法可以抛出UnsupportedOperationException。HttpClient内部使用
writeTo
将实体内容流式输出到底层HTTP连接。

我认为可以安全地假设您的请求实体不会调用getContent方法,这正是这个问题所建议的-。我想如果你真的想确定的话,你可以问一下hc邮件列表。难道你不知道呼叫者什么时候关闭了
InputStream
吗?@immibis他们为什么要关闭它?我打开了它,所以它是属于我的。@stringy05该死,它看起来像是我复制的。我也非常努力地搜索…@Trejkaz调用
getInputStream
的人会关闭返回的流。