Я намерен написать структурированные данные для доступа к ресурсу через HTTP-клиент. API для этого (для JSON, YAML, XML), как правило, заставляют меня передавать им OutputStream
, на которые они будут писать - они не дают мне InputStream
.Могу ли я пропустить реализацию HttpEntity # getContent()?
К счастью, HTTP-компоненты Apache HttpClient - это клиент, который используется здесь. (Другие библиотеки, которые мы используем, зависят от этого. Это не совсем плохо по большей части и по крайней мере не заставляет нас использовать странные нитки-локальные хаки, чтобы получить нормальное поведение, в отличие от java.net.URL
.)
При оформлении запроса , HttpEntityEnclosingRequestBase
(в HttpClient) заставляет меня установить HttpEntity
для получения любых данных на сервер. HttpEntity
, казалось бы, заставляет меня реализовать getContent()
, возвращая InputStream
.
не имеет InputStream
, поэтому я вынужден выбирать между двумя обходными:
A) сериализацией всех данных в массив байт в памяти, а затем поток все это обратно. Я не хочу этого делать, потому что, как правило, сериализованная форма данных занимает гораздо больше памяти, чем сами данные, и в некоторых случаях мы даже не имеем ее в памяти в первую очередь, так что это просите о неприятностях.
B) Создать Pipe
. Вращайте второй поток, чтобы записать объект в конец трубы OutputStream
. Верните конец InputStream
. Это фактически не может быть сделано в самом 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. Или он должен быть документирован, чтобы хотя бы разрешить мне какой-либо выход из его реализации. В любом случае я намерен записать ошибку об этом, потому что это чрезвычайно неудобно принудительно предоставлять InputStream
, когда вы пытаетесь написать запрос.)
Я думаю, было бы безопасно предположить, что ваш объект запроса не будет вызван методом getContent, это именно то, что предлагает этот вопрос - http: // stackoverflow.ком/вопросы/10146692/как-делать-я-записи к ан-OutputStream-используя-defaulthttpclient. Я думаю, если вы хотите быть уверенным, что можете запросить список рассылки hc. – stringy05
Разве вы не знаете, когда вызывающий абонент закончил «InputStream», когда они его закрыли? – immibis
@immibis Зачем они закрывают его? Я открыл его, поэтому он принадлежит мне. – Trejkaz