Module java.net.http
Package java.net.http

Class HttpResponse.BodySubscribers

java.lang.Object
java.net.http.HttpResponse.BodySubscribers
封装接口:
HttpResponse<T>

public static class HttpResponse.BodySubscribers extends Object
实现了BodySubscriber的各种有用的订阅者,例如将响应体字节转换为字符串,或将字节流式传输到文件中。

以下是使用预定义的body订阅者将响应体数据流转换为常见高级Java对象的示例:

// 将响应体流式传输到文件
HttpResponse<Path> response = client
  .send(request, responseInfo -> BodySubscribers.ofFile(Paths.get("example.html"));
// 累积响应体并将其作为字节数组返回
HttpResponse<byte[]> response = client
  .send(request, responseInfo -> BodySubscribers.ofByteArray());
// 丢弃响应体
HttpResponse<Void> response = client
  .send(request, responseInfo -> BodySubscribers.discarding());
// 累积响应体作为字符串,然后将其映射为其字节数组
HttpResponse<byte[]> response = client
  .send(request, responseInfo ->
     BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), String::getBytes));
自 JDK 版本:
11
  • Method Details

    • fromSubscriber

      public static HttpResponse.BodySubscriber<Void> fromSubscriber(Flow.Subscriber<? super List<ByteBuffer>> subscriber)
      返回一个将所有响应体逐行转发给给定Flow.Subscriber的body订阅者。返回的body订阅者的完成阶段在给定的订阅者的onCompleteonError中的一个被调用后完成。
      API 注释:
      此方法可用作BodySubscriberFlow.Subscriber之间的适配器。
      参数:
      subscriber - 订阅者
      返回:
      一个body订阅者
    • fromSubscriber

      public static <S extends Flow.Subscriber<? super List<ByteBuffer>>, T> HttpResponse.BodySubscriber<T> fromSubscriber(S subscriber, Function<? super S,? extends T> finisher)
      返回一个将所有响应体逐行转发给给定Flow.Subscriber的body订阅者。返回的body订阅者的完成阶段在给定的订阅者的onCompleteonError中的一个被调用后完成。

      给定的finisher函数在给定订阅者的onComplete被调用后应用。finisher函数与给定的订阅者一起调用,并返回一个作为响应体设置的值。

      API 注释:
      此方法可用作BodySubscriberFlow.Subscriber之间的适配器。
      类型参数:
      S - 订阅者的类型
      T - 响应体的类型
      参数:
      subscriber - 订阅者
      finisher - 在订阅者完成后应用的函数
      返回:
      一个body订阅者
    • fromLineSubscriber

      public static HttpResponse.BodySubscriber<Void> fromLineSubscriber(Flow.Subscriber<? super String> subscriber)
      返回一个将所有响应体逐行转发给给定Flow.Subscriber的body订阅者。返回的body订阅者的完成阶段在给定的订阅者的onCompleteonError中的一个被调用后完成。字节使用UTF-8字符集进行解码,行以BufferedReader.readLine()的方式分隔。
      API 注释:
      此方法可用作BodySubscriberFlow.Subscriber之间的适配器。
      实现注释:
      这等效于调用
      fromLineSubscriber(subscriber, s -> null, StandardCharsets.UTF_8, null)
      参数:
      subscriber - 订阅者
      返回:
      一个body订阅者
    • fromLineSubscriber

      public static <S extends Flow.Subscriber<? super String>, T> HttpResponse.BodySubscriber<T> fromLineSubscriber(S subscriber, Function<? super S,? extends T> finisher, Charset charset, String lineSeparator)
      返回一个将所有响应体逐行转发给给定Flow.Subscriber的body订阅者。返回的body订阅者的完成阶段在给定的订阅者的onCompleteonError中的一个被调用后完成。

      给定的finisher函数在给定订阅者的onComplete被调用后应用。finisher函数与给定的订阅者一起调用,并返回一个作为响应体设置的值。

      API 注释:
      此方法可用作BodySubscriberFlow.Subscriber之间的适配器。
      类型参数:
      S - 订阅者的类型
      T - 响应体的类型
      参数:
      subscriber - 订阅者
      finisher - 在订阅者完成后应用的函数
      charset - 用于解码字节的Charset
      lineSeparator - 可选的行分隔符:可以为null,在这种情况下,行将以BufferedReader.readLine()的方式分隔。
      返回:
      一个body订阅者
      抛出:
      IllegalArgumentException - 如果提供的lineSeparator是空字符串
    • ofString

      public static HttpResponse.BodySubscriber<String> ofString(Charset charset)
      返回一个将响应体存储为使用给定Charset转换的StringBodySubscriber

      使用此订阅者的HttpResponse在整个响应读取完毕后可用。

      参数:
      charset - 用于转换字符串的字符集
      返回:
      一个body订阅者
    • ofByteArray

      public static HttpResponse.BodySubscriber<byte[]> ofByteArray()
      返回一个将响应体存储为字节数组的BodySubscriber

      使用此订阅者的HttpResponse在整个响应读取完毕后可用。

      返回:
      一个body订阅者
    • ofFile

      public static HttpResponse.BodySubscriber<Path> ofFile(Path file, OpenOption... openOptions)
      返回一个BodySubscriber,将响应体存储在使用给定选项和名称打开的文件中。文件将在读取响应体之前使用FileChannel.open打开。任何抛出的异常将从HttpClient::sendHttpClient::sendAsync中返回或抛出。

      使用此订阅器的HttpResponse在整个响应读取完成后可用。

      在默认文件系统提供程序的情况下,在创建BodySubscriber时将执行安全管理器权限检查。否则,可能会在文件访问时异步执行权限检查。必须注意不要将BodySubscriber与不受信任的代码共享。

      参数:
      file - 要存储响应体的文件
      openOptions - 打开文件时要使用的选项列表
      返回:
      一个body订阅器
      抛出:
      IllegalArgumentException - 如果指定了无效的打开选项集
      SecurityException - 在默认文件系统提供程序的情况下,并且安装了安全管理器,将调用checkWrite来检查对给定文件的写访问权限
    • ofFile

      public static HttpResponse.BodySubscriber<Path> ofFile(Path file)
      返回一个BodySubscriber,将响应体存储在使用给定名称打开的文件中。

      等效于:ofFile(file, CREATE, WRITE)

      在默认文件系统提供程序的情况下,在创建BodySubscriber时将执行安全管理器权限检查。否则,可能会在文件访问时异步执行权限检查。必须注意不要将BodySubscriber与不受信任的代码共享。

      参数:
      file - 要存储响应体的文件
      返回:
      一个body订阅器
      抛出:
      SecurityException - 在默认文件系统提供程序的情况下,并且安装了安全管理器,将调用checkWrite来检查对给定文件的写访问权限
    • ofByteArrayConsumer

      public static HttpResponse.BodySubscriber<Void> ofByteArrayConsumer(Consumer<Optional<byte[]>> consumer)
      返回一个BodySubscriber,将传入的响应体数据提供给Optional<byte[]>的Consumer。每次调用Consumer.accept()都将包含一个非空的Optional,除了在读取所有响应体数据后的最后调用,此时Optional将为空。

      使用此订阅器的HttpResponse在整个响应读取完成后可用。

      API 注意:
      此订阅器不受流控制。因此,提供的消费者必须能够及时处理传递的任何数据量。
      参数:
      consumer - 一个字节数组的Consumer
      返回:
      一个BodySubscriber
    • ofInputStream

      public static HttpResponse.BodySubscriber<InputStream> ofInputStream()
      返回一个BodySubscriber,将响应体作为InputStream流式传输。

      使用此订阅器的HttpResponse在读取响应头后立即可用,无需等待整个响应体被处理。然后可以直接从InputStream中读取响应体。

      API 注意:
      为确保释放与相应交换相关的所有资源,调用方必须确保要么读取所有字节直到达到EOF,要么在无法或不愿这样做时调用InputStream.close()。在耗尽流之前调用close可能会导致底层HTTP连接被关闭,并阻止其被用于后续操作。
      实现注意:
      由此方法的默认实现返回的InputStreamread方法在阻塞读取时如果线程被中断将抛出一个带有线程中断状态设置IOException。在这种情况下,请求也将被取消,并且InputStream将被关闭。
      返回:
      一个将响应体作为InputStream流式传输的body订阅器。
    • ofLines

      public static HttpResponse.BodySubscriber<Stream<String>> ofLines(Charset charset)
      返回一个BodySubscriber,将响应体作为Stream<String>流式传输,流中的每个字符串对应于由BufferedReader.lines()定义的一行。

      使用此订阅器的HttpResponse在读取响应头后立即可用,无需等待整个响应体被处理。然后可以直接从Stream中读取响应体。

      API 注意:
      为确保释放与相应交换相关的所有资源,调用方必须确保要么读取所有行直到流耗尽,要么在无法或不愿这样做时调用BaseStream.close()。在耗尽流之前调用close可能会导致底层HTTP连接被关闭,并阻止其被用于后续操作。
      参数:
      charset - 将字节转换为字符时要使用的字符集
      返回:
      一个将响应体作为Stream<String>流式传输的body订阅器。
      参见:
    • ofPublisher

      public static HttpResponse.BodySubscriber<Flow.Publisher<List<ByteBuffer>>> ofPublisher()
      返回一个响应订阅器,通过Publisher<List<ByteBuffer>>发布响应体字节。

      使用此订阅器的HttpResponse在读取响应头后立即可用,无需等待整个响应体被处理。然后可以通过订阅HttpResponsebody方法返回的发布者获取响应体字节。

      通过HttpResponsebody方法返回的发布者只能订阅一次。第一个订阅者将在成功订阅时接收响应体字节,否则将导致订阅被取消。如果尝试进行更多订阅,则后续订阅者将立即被订阅为空订阅,并且它们的onError方法将使用IllegalStateException调用。

      API 注意:
      为确保释放与相应交换相关的所有资源,调用方必须确保提供的发布者只订阅一次,并且要么请求所有字节直到onCompleteonError被调用,要么取消提供的订阅。请注意,根据用于交换的实际HTTP协议版本,取消订阅而不是耗尽流可能会导致底层HTTP连接被关闭,并阻止其被用于后续操作。
      返回:
      一个通过Publisher<List<ByteBuffer>>发布响应体字节的BodySubscriber
    • replacing

      public static <U> HttpResponse.BodySubscriber<U> replacing(U value)
      返回一个响应订阅器,丢弃响应体。提供的值是从HttpResponse.body()返回的值。
      类型参数:
      U - 响应体的类型
      参数:
      value - 从HttpResponse.body()返回的值,可以为null
      返回:
      一个BodySubscriber
    • discarding

      public static HttpResponse.BodySubscriber<Void> discarding()
      返回一个丢弃响应体的响应订阅器。
      返回:
      一个响应体订阅器
    • buffering

      public static <T> HttpResponse.BodySubscriber<T> buffering(HttpResponse.BodySubscriber<T> downstream, int bufferSize)
      返回一个BodySubscriber,在将数据传递给给定的下游订阅者之前对数据进行缓冲。该订阅者保证在每次调用下游的onNext方法时传递bufferSize字节的数据,除了在调用onComplete之前的最后一次调用。最后一次调用onNext可能包含少于bufferSize字节的数据。

      返回的订阅者将其getBody()方法委托给下游订阅者。

      类型参数:
      T - 响应体的类型
      参数:
      downstream - 下游订阅者
      bufferSize - 缓冲区大小
      返回:
      一个缓冲体订阅者
      抛出:
      IllegalArgumentException - 如果bufferSize <= 0
    • mapping

      public static <T, U> HttpResponse.BodySubscriber<U> mapping(HttpResponse.BodySubscriber<T> upstream, Function<? super T,? extends U> mapper)
      返回一个BodySubscriber,其响应体值是将给定函数应用于给定upstream BodySubscriber的响应体对象的结果。

      映射函数使用客户端的executor执行,因此可以用于映射任何响应体类型,包括阻塞的InputStream。然而,在映射函数中执行任何阻塞操作会导致阻塞执行程序的线程一段未知的时间(至少直到阻塞操作完成),这可能会导致执行程序缺乏可用线程。因此,在映射到所需类型可能会阻塞的情况下(例如通过读取InputStream),应优先将映射为所需类型的Supplier并将阻塞操作推迟到调用者线程调用Supplier::get时执行,如下例所示,该例使用一个众所周知的JSON解析器将InputStream转换为任何注释的Java类型。

      例如:

       public static <W> BodySubscriber<Supplier<W>> asJSON(Class<W> targetType) {
         BodySubscriber<InputStream> upstream = BodySubscribers.ofInputStream();
      
         BodySubscriber<Supplier<W>> downstream = BodySubscribers.mapping(
               upstream,
               (InputStream is) -> () -> {
                   try (InputStream stream = is) {
                       ObjectMapper objectMapper = new ObjectMapper();
                       return objectMapper.readValue(stream, targetType);
                   } catch (IOException e) {
                       throw new UncheckedIOException(e);
                   }
               });
        return downstream;
      }
      类型参数:
      T - 上游体类型
      U - 返回的体订阅者的类型
      参数:
      upstream - 要映射的体订阅者
      mapper - 映射函数
      返回:
      一个映射体订阅者