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
-
Готовые реализации
BodyPublisher,BodyHandlerиBodySubscriber, создаваемые статическими фабричными методами, вынесены в отдельные вспомогательные фабричные классы без возможности создания экземпляров, названные по соглашению о множественном числе. Это делает эти относительно небольшие интерфейсы удобнее для чтения. -
Имена статических фабричных методов также обновлены по следующим общим категориям:
-
fromXxx: адаптеры от стандартного Subscriber, например принимаютFlow.Subscriberи возвращаютBodySubscriber. -
ofXxx: фабрики, которые создают новый готовыйBody[Publisher|Handler|Subscriber], выполняющий полезные типовые задачи, например обработку тела ответа как String или потоковую запись тела в File. -
прочее: комбинаторы (принимают
BodySubscriberи возвращаютBodySubscriber) и другие полезные операции.
- Добавлено несколько
BodyHandlerи соответствующих имBodySubscriber, чтобы было удобнее работать в типичных сценариях:
-
discard(Object replacement)совмещал отбрасывание/игнорирование тела ответа с возможностью задать замену. Отзывы показали, что это может сбивать с толку. Этот обработчик удалён и заменён двумя отдельными обработчиками: 1)discarding()и 2)replacing(Object replacement). -
Добавлен
ofLines(), который возвращаетBodyHandler<Stream<String>>, для потоковой передачи тела ответа в видеStreamстрок, строка за строкой. Семантика аналогичнаBufferedReader.lines(). -
Добавлен
fromLineSubscriber, который поддерживает адаптацию тела ответа кFlow.SubscriberстрокString. -
Добавлен
BodySubscriber.mappingдля преобразования одного типа тела ответа в другой в общем случае.
-
Поддержка push promise переработана, чтобы уменьшить её влияние на API и приблизить её к обычным запросам и ответам. В частности, удалены
MultiSubscriberиMultiResultMap. Теперь push promise обрабатываются через функциональный интерфейсPushPromiseHandler, который можно передать при операции отправки. -
Политика
HttpClient.Redirectупрощена: политикиSAME_PROTOCOLиSECUREзаменены наNORMAL. Выяснилось, что прежнее имяSECUREбыло выбрано не совсем удачно и его следует заменить наNORMAL, поскольку эта политика, скорее всего, подойдёт для большинства обычных случаев. С учётом нового имениNORMAL, упомянутого выше, имяSAME_PROTOCOLвыглядит странно, может сбивать с толку, и эта политика вряд ли будет использоваться. -
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-модулей, уже получает соответствующее предупреждение и при компиляции, и во время выполнения.