openjdk.ruOpenJDK на русском

JEP 321: HTTP Client API

HTTP Client API

ОтветственныйChris Hegarty
ТипFeature
ОбластьSE
СтатусClosed / Delivered
Выпуск11
Компонентcore-libs / java.net
Обсуждениеnet dash dev at openjdk dot java dot net
ТрудоёмкостьM
ДлительностьM
Связан сJEP 110: HTTP/2 Client (Incubator)
JEP 517: HTTP/3 for the HTTP Client API
РецензентыAlan Bateman, Brian Goetz
ОдобренBrian Goetz
Создан2017/06/08 11:46
Обновлён2024/08/27 14:42
Задача8181784

Аннотация

Стандартизировать HTTP Client API, который появился в JDK 9 в статусе Incubator (инкубационный модуль) в рамках JEP 110 и был обновлён в JDK 10.

Цели

Помимо целей JEP 110, этот JEP:

  • учтёт отзывы, полученные на API в статусе Incubator;
  • предоставит стандартизированный API в пакете java.net.http на основе API в статусе Incubator;
  • удалит API в статусе Incubator.

Мотивация

Мотивация этого JEP та же, что и мотивация JEP 110.

Описание

Этот JEP предлагает стандартизировать HTTP Client API, который появился в статусе Incubator в JDK 9 и был обновлён в JDK 10. API в статусе Incubator прошёл несколько циклов обратной связи, которые привели к значительным улучшениям, но в целом он остался почти прежним. API обеспечивает неблокирующую семантику запросов и ответов через CompletableFuture, которые можно объединять в цепочки, чтобы запускать зависимые действия. Обратное давление (back-pressure) и управление потоком данных для тел запросов и ответов обеспечиваются поддержкой reactive streams в платформе, в API java.util.concurrent.Flow.

За время нахождения в статусе Incubator в JDK 9 и JDK 10 реализация была почти полностью переписана. Теперь реализация полностью асинхронна (прежняя реализация HTTP/1.1 была блокирующей). Концепция RX Flow теперь используется на уровне реализации, что позволило отказаться от многих изначальных собственных концепций, нужных для поддержки HTTP/2. Теперь движение данных проще проследить — от издателей запросов и подписчиков ответов на пользовательском уровне до нижележащего сокета. Это значительно сокращает число концепций и сложность кода и даёт максимум возможностей для повторного использования кода между HTTP/1.1 и HTTP/2.

Имя модуля и имя пакета стандартного API будут java.net.http.

Изменения по сравнению с версией в статусе Incubator из JDK 10

  1. Готовые реализации BodyPublisher, BodyHandler и BodySubscriber, создаваемые статическими фабричными методами, вынесены в отдельные вспомогательные фабричные классы без возможности создания экземпляров, названные по соглашению о множественном числе. Это делает эти относительно небольшие интерфейсы удобнее для чтения.

  2. Имена статических фабричных методов также обновлены по следующим общим категориям:

  • fromXxx: адаптеры от стандартного Subscriber, например принимают Flow.Subscriber и возвращают BodySubscriber.

  • ofXxx: фабрики, которые создают новый готовый Body[Publisher|Handler|Subscriber], выполняющий полезные типовые задачи, например обработку тела ответа как String или потоковую запись тела в File.

  • прочее: комбинаторы (принимают BodySubscriber и возвращают BodySubscriber) и другие полезные операции.

  1. Добавлено несколько BodyHandler и соответствующих им BodySubscriber, чтобы было удобнее работать в типичных сценариях:
  • discard(Object replacement) совмещал отбрасывание/игнорирование тела ответа с возможностью задать замену. Отзывы показали, что это может сбивать с толку. Этот обработчик удалён и заменён двумя отдельными обработчиками: 1) discarding() и 2) replacing(Object replacement).

  • Добавлен ofLines(), который возвращает BodyHandler<Stream<String>>, для потоковой передачи тела ответа в виде Stream строк, строка за строкой. Семантика аналогична BufferedReader.lines().

  • Добавлен fromLineSubscriber​, который поддерживает адаптацию тела ответа к Flow.Subscriber строк String.

  • Добавлен BodySubscriber.mapping для преобразования одного типа тела ответа в другой в общем случае.

  1. Поддержка push promise переработана, чтобы уменьшить её влияние на API и приблизить её к обычным запросам и ответам. В частности, удалены MultiSubscriber и MultiResultMap. Теперь push promise обрабатываются через функциональный интерфейс PushPromiseHandler, который можно передать при операции отправки.

  2. Политика HttpClient.Redirect упрощена: политики SAME_PROTOCOL и SECURE заменены на NORMAL. Выяснилось, что прежнее имя SECURE было выбрано не совсем удачно и его следует заменить на NORMAL, поскольку эта политика, скорее всего, подойдёт для большинства обычных случаев. С учётом нового имени NORMAL, упомянутого выше, имя SAME_PROTOCOL выглядит странно, может сбивать с толку, и эта политика вряд ли будет использоваться.

  3. WebSocket.MessagePart удалён. Это перечисление использовалось на принимающей стороне, чтобы указать, завершена доставка сообщения или нет. Оно несимметрично отправляющей стороне, где для этой цели используется простой boolean. Кроме того, выяснилось, что обработка полученных сообщений с помощью простого boolean значительно сокращает и упрощает логику принимающего кода. Возможность определить, что сообщения доставляются как WHOLE, — одно из преимуществ и главных назначений упомянутого MessagePart — себя не оправдала.

Подробнее об API можно узнать в JEP 110, в актуальной документации javadoc по API или на странице JDK HTTP Client группы networking.

Тестирование

Существующие тесты для API в статусе Incubator будут обновлены для использования нового стандартного API. Будут добавлены новые тесты, покрывающие все поддерживаемые сценарии, в частности переход с HTTP/1.1 на HTTP/2 и обратно.

Риски и допущения

Код, который сейчас зависит от HTTP Client API в статусе Incubator, придётся обновить — как минимум изменить импорты пакетов. Здесь нет отличий от любой другой возможности в статусе Incubator. Код, зависящий от Incubator-модулей, уже получает соответствующее предупреждение и при компиляции, и во время выполнения.