Skip to content

JEP 321: HTTP Client

摘要

通过 JEP 110,将 JDK 9 中引入的孵化中的 HTTP Client API 进行标准化,并在 JDK 10 中进行了更新。

目标

除了 JEP 110 的目标 外,此 JEP 将:

  • 考虑对孵化中 API 的反馈,
  • 基于孵化中 API,在 java.net.http 包中提供一个标准化的 API,
  • 移除孵化中 API。

动机

此 JEP 的动机与 JEP 110 的动机 保持一致。

描述

此 JEP 提议将 JDK 9 中作为孵化 API 引入并在 JDK 10 中更新的 HTTP Client API 进行标准化。孵化 API 已经收到了多轮反馈,这些反馈导致了显著的改进,但大体上它仍然保持不变。该 API 通过 CompletableFuture 提供非阻塞的请求和响应语义,这些 CompletableFuture 可以链接以触发依赖的操作。通过平台在 java.util.concurrent.Flow API 中对 reactive-streams 的支持,提供了对请求和响应体的背压和流量控制。

在 JDK 9 和 JDK 10 中孵化时,该实现已被几乎完全重写。现在的实现完全是异步的(之前的 HTTP/1.1 实现是阻塞的)。RX Flow 概念的使用已经深入到实现中,这消除了许多原本需要支持 HTTP/2 的自定义概念。现在,从用户级别的请求发布者和响应订阅者,一直到底层套接字,数据的流动都可以更容易地被追踪。这大大减少了代码中的概念和复杂性,并最大限度地提高了 HTTP/1.1 和 HTTP/2 之间的重用可能性。

标准化的 API 的模块名和包名将是 java.net.http

关于在 JDK 10 中孵化后的更改

  1. BodyPublisher、BodyHandler 和 BodySubscriber 的预定义实现:通过静态工厂方法创建的 BodyPublisherBodyHandlerBodySubscriber 的预定义实现,已被移到单独的不可实例化的实用工厂类中,遵循了复数命名约定。这提高了这些相对较小的接口的可读性。

  2. 静态工厂方法名称的更新:静态工厂方法的名称也按照以下大致类别进行了更新:

    • fromXxx:从标准 Subscriber 适配器创建,例如接收一个 Flow.Subscriber 并返回一个 BodySubscriber

    • ofXxx:创建执行有用通用任务的预定义 Body[Publisher|Handler|Subscriber] 的工厂,例如将响应体处理为字符串,或将响应体流式传输到文件。

    • 其他:组合器(接收一个 BodySubscriber 并返回一个 BodySubscriber)和其他有用的操作。

  3. 添加了一些 BodyHandler 和对应的 BodySubscriber,以改善常见场景中的可用性:

    • discard(Object replacement):结合了丢弃 / 忽略响应体和允许给定替换物的功能。反馈表明这可能会造成混淆。因此,它已被移除,并替换为两个单独的处理器:1) discarding(),和 2) replacing(Object replacement)

    • 添加了 ofLines(),它返回一个 BodyHandler<Stream<String>>,以支持将响应体作为行的 Stream 进行流式传输,逐行读取。提供了与 BufferedReader.lines() 相似的语义。

    • 添加了 fromLineSubscriber,它支持将响应体适配为 String 行的 Flow.Subscriber

    • 添加了 BodySubscriber.mapping,用于从一种响应体类型到另一种响应体类型的通用映射。

  4. HttpClient.Redirect 策略的简化:通过用 NORMAL 策略替换之前的 SAME_PROTOCOLSECURE 策略,HttpClient.Redirect 策略已经得到简化。人们发现,之前名为 SECURE 的策略名称并不十分恰当,应该重命名为 NORMAL,因为它可能适用于大多数正常情况。鉴于新命名的 NORMALSAME_PROTOCOL 看起来命名有些奇怪,可能会造成混淆,并且不太可能被使用。

  5. WebSocket.MessagePart 的移除:这个枚举在接收端用于指示消息的传递是否完整。然而,它与发送端是不对称的,发送端只使用一个简单的布尔值来表示这个目的。此外,已经发现使用简单的布尔值来处理接收到的消息可以大大减少和简化接收代码的逻辑。确定消息作为 WHOLE 传递(这是 MessagePart 的主要目的之一)被证明并没有它自身的价值。

你可以在 JEP 110(Java 增强提案 110)中找到关于 API 的更多具体信息,或者在 最新的 API javadoc 中查看,或者访问网络组的 JDK HTTP Client 页面。

测试

针对孵化 API 的现有测试将被更新以使用新的标准 API。将添加额外的测试来覆盖所有支持的场景,特别是 HTTP/1.1 和 HTTP/2 之间的升级和降级。

风险和假设

当前依赖于孵化 HTTP Client API 的代码将需要进行更新,至少需要更改其包导入。这与任何其他孵化特性都没有区别。依赖于孵化模块的代码在编译时和运行时都会收到适当的警告。