简体   繁体   English

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

[英]Can I skip implementing HttpEntity#getContent()?

I intend to write structured data to a resource accessed via an HTTP client. 我打算将结构化数据写入通过HTTP客户端访问的资源。 APIs for doing this (for JSON, YAML, XML) tend to make me pass them an OutputStream which they will write to - they don't give me an InputStream . 用于执行此操作的API(针对JSON,YAML,XML)通常使我将它们传递给他们的OutputStream传递给它们-它们没有给我InputStream

For better or worse, the Apache HTTP Components HttpClient is the client being used here. 不管是好是坏,Apache HTTP Components HttpClient是此处使用的客户端。 (Other libraries we use depend on it. It's not entirely bad for the most part and at least doesn't force us to employ weird thread-local hacks just to get sane behaviour, unlike java.net.URL .) (我们使用的其他库依赖于它。在大多数情况下,这并不完全不好,至少不强迫我们使用怪异的线程本地hack来获得理智的行为,这与java.net.URL不同。)

When making a request, HttpEntityEnclosingRequestBase (in HttpClient) forces me to set an HttpEntity to get any data to the server. 发出请求时, HttpEntityEnclosingRequestBase (在HttpClient中)迫使我设置HttpEntity以将任何数据发送到服务器。 HttpEntity seemingly forces me to implement getContent() , returning an InputStream . HttpEntity似乎迫使我实现getContent() ,并返回InputStream

I don't have an InputStream , so I am forced to choose between two workarounds: 我没有InputStream ,所以我不得不在两种解决方法之间进行选择:

A) Serialise all the data into an in-memory byte array and then stream it all back out again. A)将所有数据序列化为内存中的字节数组,然后再次将其全部流回。 I don't want to do this, because usually, the serialised form of the data takes up a lot more memory than the data itself, and in some cases we don't even have it in memory in the first place, so this would be asking for trouble. 我不想这样做,因为通常情况下,数据的序列化形式要比数据本身占用更多的内存,并且在某些情况下,我们甚至根本不将其存储在内存中,因此这会自找麻烦。

B) Create a Pipe . B)创建一个Pipe Spin up a second thread to write the object to the OutputStream end of the pipe. 旋转第二个线程以将该对象写入管道的OutputStream末端。 Return the InputStream end. 返回InputStream结束。 This can't actually be done in HttpEntity itself, because HttpEntity has no idea when the data stream is no longer needed. 实际上,这不能在HttpEntity本身中完成,因为HttpEntity不知道何时不再需要数据流。 (It could make an educated guess that it's done when you reach the end of the stream, but if the connection to the server dropped half way, you'd leave the pipe open forever.) This means I end up moving the workaround to every place where a connection is made, which is a lot of structural duplication. (这可以引起人们有根据的猜测,当您到达流的末尾时就已经完成了,但是如果与服务器的连接中途掉线了,您将永远保持管道畅通。)这意味着我最终将解决方法转移到每个建立连接的地方,这是很多结构上的重复。

Neither of these workarounds is great, but I guess (B) is "less shit" because it at least won't crash the entire application when a large object is transferred. 这些变通办法都不是很好,但是我猜(B)的“狗屎少”,因为它至少不会在传输大对象时使整个应用程序崩溃。

Here's as far as I got: 就我所知:

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;
}

Now I'm wondering if getContent() can just throw UnsupportedOperationException. 现在我想知道getContent()可以抛出UnsupportedOperationException。 Surely when making a request, they would be using writeTo() anyway, right? 当然,在发出请求时,他们还是会使用writeTo() ,对吧? Well, I can't figure it out. 好吧,我不知道。 Even if it works in one experiment, that wouldn't assure me that it is impossible for some kind of request to demand a call to getContent() . 即使它可以在一个实验中工作,也不能保证我无法通过某种请求来要求调用getContent()

So I'm wondering if anyone who knows this library better than me can make a call on it - is it safe to skip implementing this method? 因此,我想知道是否有人比我更了解此库,所以可以调用它-跳过实现此方法是否安全?

(This getContent() method just seems like it shouldn't be in the API. Or it should be documented to at least allow me some way out of implementing it. I intend to file a bug about it anyway, because it's extremely inconvenient to be forced to provide an InputStream when you are trying to write a request.) (此getContent()方法似乎不应该包含在API中。或者应该对其进行记录,以至少允许我以某种方式实现它。我打算无论如何都要提交一个错误,因为这样做非常不便在您尝试编写请求时被迫提供InputStream 。)

If entity content cannot be represented as an InputStream getContent method can throw UnsupportedOperationException. 如果实体内容不能表示为InputStream,则getContent方法可以引发UnsupportedOperationException。 Internally HttpClient uses writeTo to stream out entity content to the underlying HTTP connection. 在内部,HttpClient使用writeTo将实体内容流式传输到基础HTTP连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 (java)HttpEntity.getContent()输出受限的InputStream(8192b / 7748b)…我正在尝试下载2.4MB文件 - (java) HttpEntity.getContent() outputs limited InputStream (8192b / 7748b) … I'm trying to download a 2.4MB file JAVA使用IOUtils.toString和HttpEntity.getContent()将InputStream转换为null - JAVA Using IOUtils.toString with HttpEntity.getContent() converting the InputStream to null 关闭连接后,如何使HttpResponse的HttpEntity字段持久化? - How can I make the HttpEntity field of an HttpResponse persist after closing the connection? 如何在不使用HttpEntity的情况下阅读它? - How do I read HttpEntity without consuming it? 如何修改HttpEntity的内容 - How do I modify the content of an HttpEntity HttpEntity <String> request = new HttpEntity <String> (); 我如何在java中模拟它 - HttpEntity<String> request = new HttpEntity<String>( ); How do I mock this in java 如何跳过此代码中的“ \\ n” - how can I skip the '\n' in this code 协议验证:我可以跳过特定的 providerState - Pact Verification: Can i skip a particular providerState nutch content.getContent()无法返回整个结果 - nutch content.getContent() can not return entire results 我正在获取HttpResponse,但是responce.getEntity()。getContent()显示NullPointerException - I am getting HttpResponse but responce.getEntity().getContent() shows NullPointerException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM