[英]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.