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

Class HttpResponse.BodyHandlers

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

public static class HttpResponse.BodyHandlers extends Object
实现了BodyHandler的各种有用的处理程序,例如将响应体作为字符串处理,或将响应体流式传输到文件中。

这些实现不会检查状态码,意味着始终接受响应体。它们通常返回一个同名的BodySubscriber。或者,可以使用自定义处理程序来检查状态码和标头,并根据需要返回不同类型的响应体订阅者。

以下是使用预定义的响应体处理程序将响应体数据流转换为常见高级Java对象的示例:

// 将响应体作为字符串接收
HttpResponse<String> response = client
  .send(request, BodyHandlers.ofString());
// 将响应体作为文件接收
HttpResponse<Path> response = client
  .send(request, BodyHandlers.ofFile(Paths.get("example.html")));
// 将响应体作为InputStream接收
HttpResponse<InputStream> response = client
  .send(request, BodyHandlers.ofInputStream());
// 丢弃响应体
HttpResponse<Void> response = client
  .send(request, BodyHandlers.discarding());
自 JDK 版本:
11
  • Method Details

    • fromSubscriber

      public static HttpResponse.BodyHandler<Void> fromSubscriber(Flow.Subscriber<? super List<ByteBuffer>> subscriber)
      返回一个从HttpResponse.BodySubscribers.fromSubscriber(Subscriber)获取的BodySubscriber<Void>的响应体处理程序,使用给定的subscriber

      响应体不通过此方法或HttpResponse API可用,而是所有响应体都转发给给定的subscriber,如果适用,应通过其他机制(例如数据库中的条目等)使其可用。

      API 注释:
      此方法可用作BodySubscriberFlow.Subscriber之间的适配器。

      例如:

      TextSubscriber subscriber = new TextSubscriber();
      HttpResponse<Void> response = client.sendAsync(request,
          BodyHandlers.fromSubscriber(subscriber)).join();
      System.out.println(response.statusCode());
      参数:
      subscriber - 订阅者
      返回:
      一个响应体处理程序
    • fromSubscriber

      public static <S extends Flow.Subscriber<? super List<ByteBuffer>>, T> HttpResponse.BodyHandler<T> fromSubscriber(S subscriber, Function<? super S,? extends T> finisher)
      返回一个从HttpResponse.BodySubscribers.fromSubscriber(Subscriber, Function)获取的BodySubscriber<T>的响应体处理程序,使用给定的subscriberfinisher函数。

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

      API注释:
      此方法可用作BodySubscriberFlow.Subscriber之间的适配器。

      例如:

      TextSubscriber subscriber = ...;  // 累积字节并将其转换为字符串
      HttpResponse<String> response = client.sendAsync(request,
          BodyHandlers.fromSubscriber(subscriber, TextSubscriber::getTextResult)).join();
      String text = response.body();
      类型参数:
      S - Subscriber的类型
      T - 响应体的类型
      参数:
      subscriber - 订阅者
      finisher - 在订阅者完成后应用的函数
      返回:
      一个响应体处理程序
    • fromLineSubscriber

      public static HttpResponse.BodyHandler<Void> fromLineSubscriber(Flow.Subscriber<? super String> subscriber)
      返回一个响应体处理程序,该处理程序从BodySubscriber<Void>中获取,方法为BodySubscribers.fromLineSubscriber(subscriber, s -> null, charset, null),使用给定的subscriber。用于解码响应体字节的charset从HTTP响应头中获取,如ofString()所指定,并且行以BufferedReader.readLine()的方式分隔。

      响应体不能通过此方法或HttpResponse API获得,而是所有响应体都转发给给定的subscriber,如果适用,应通过其他机制(例如数据库中的条目等)使其可用。

      API注释:
      此方法可用作BodySubscriber和基于文本的Flow.Subscriber之间的适配器,逐行解析文本。

      例如:

      // 一个实现Flow.Subscriber<String>并在System.out上打印接收到的行的PrintSubscriber
      PrintSubscriber subscriber = new PrintSubscriber(System.out);
      client.sendAsync(request, BodyHandlers.fromLineSubscriber(subscriber))
          .thenApply(HttpResponse::statusCode)
          .thenAccept((status) -> {
              if (status != 200) {
                  System.err.printf("错误:收到%d状态%n", status);
              }
          });
      参数:
      subscriber - 订阅者
      返回:
      一个响应体处理程序
    • fromLineSubscriber

      public static <S extends Flow.Subscriber<? super String>, T> HttpResponse.BodyHandler<T> fromLineSubscriber(S subscriber, Function<? super S,? extends T> finisher, String lineSeparator)
      返回一个响应体处理程序,该处理程序从BodySubscriber<T>中获取,方法为BodySubscribers.fromLineSubscriber(subscriber, finisher, charset, lineSeparator),使用给定的subscriberfinisher函数和行分隔符。用于解码响应体字节的charset从HTTP响应头中获取,如ofString()所指定。

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

      API注释:
      此方法可用作BodySubscriber和基于文本的Flow.Subscriber之间的适配器,逐行解析文本。

      例如:

      // 一个实现Flow.Subscriber<String>并累积匹配特定模式的行的LineParserSubscriber
      Pattern pattern = ...;
      LineParserSubscriber subscriber = new LineParserSubscriber(pattern);
      HttpResponse<List<String>> response = client.send(request,
          BodyHandlers.fromLineSubscriber(subscriber, s -> s.getMatchingLines(), "\n"));
      if (response.statusCode() != 200) {
          System.err.printf("错误:%d状态%n", response.statusCode());
      }
      类型参数:
      S - Subscriber的类型
      T - 响应体的类型
      参数:
      subscriber - 订阅者
      finisher - 在订阅者完成后应用的函数
      lineSeparator - 可选的行分隔符:可以为null,在这种情况下,行将以BufferedReader.readLine()的方式分隔。
      返回:
      一个响应体处理程序
      抛出:
      IllegalArgumentException - 如果提供的lineSeparator是空字符串
    • discarding

      public static HttpResponse.BodyHandler<Void> discarding()
      返回一个丢弃响应体的响应体处理程序。
      返回:
      一个响应体处理程序
    • replacing

      public static <U> HttpResponse.BodyHandler<U> replacing(U value)
      返回一个响应体处理程序,该处理程序在丢弃响应体后返回给定的替换值。
      类型参数:
      U - 响应体类型
      参数:
      value - 作为响应体返回的U的值,可以为null
      返回:
      一个响应体处理程序
    • ofString

      public static HttpResponse.BodyHandler<String> ofString(Charset charset)
      返回一个BodyHandler<String>,该处理程序从BodySubscriber<String>中获取,方法为BodySubscribers.ofString(Charset)。使用给定的字符集解码主体。
      参数:
      charset - 用于转换主体的字符集
      返回:
      一个响应体处理程序
    • ofFile

      public static HttpResponse.BodyHandler<Path> ofFile(Path file, OpenOption... openOptions)
      返回一个BodyHandler<Path>,该处理程序从BodySubscriber<Path>中获取,方法为BodySubscribers.ofFile(Path,OpenOption...)

      当返回HttpResponse对象时,主体已完全写入文件,并且HttpResponse.body()返回对其Path的引用。

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

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

      public static HttpResponse.BodyHandler<Path> ofFile(Path file)
      返回一个BodyHandler<Path>,该处理程序从BodySubscriber<Path>中获取。

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

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

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

      public static HttpResponse.BodyHandler<Path> ofFileDownload(Path directory, OpenOption... openOptions)
      返回一个BodyHandler<Path>,该方法返回一个BodySubscriber<Path>,其中下载目录已指定,但文件名是从Content-Disposition响应头中获取的。 Content-Disposition头必须指定attachment类型,并且还必须包含一个filename参数。如果文件名指定了多个路径组件,则只使用最后一个组件作为文件名(与给定目录名一起)。

      当返回HttpResponse对象时,文件体已完全写入文件,HttpResponse.body()返回一个文件的Path对象。返回的Path是提供的目录名和服务器提供的文件名的组合。如果目标目录不存在或无法写入,则响应将以IOException失败。

      在创建此工厂方法时会执行安全管理器权限检查,当创建BodyHandler时必须注意不与不受信任的代码共享BodyHandler

      参数:
      directory - 要存储文件的目录
      openOptions - 打开文件时使用的选项
      返回:
      一个响应体处理程序
      抛出:
      IllegalArgumentException - 如果给定路径不存在,不是默认文件系统的一部分,不是目录,不可写,或者指定了无效的打开选项集
      SecurityException - 在默认文件系统提供程序的情况下,安全管理器已安装,并且拒绝对目录的读取访问,或者拒绝对目录的写入访问,或者拒绝对目录中的文件的写入访问
    • ofInputStream

      public static HttpResponse.BodyHandler<InputStream> ofInputStream()
      返回一个BodyHandler<InputStream>,该方法返回一个BodySubscriber<InputStream>,从BodySubscribers.ofInputStream获得。

      当返回HttpResponse对象时,响应头将完全读取,但正文可能尚未完全接收。 HttpResponse.body()方法返回一个InputStream,可以从中读取正文,因为它被接收。

      API注释:
      有关更多信息,请参见HttpResponse.BodySubscribers.ofInputStream()
      返回:
      一个响应体处理程序
    • ofLines

      public static HttpResponse.BodyHandler<Stream<String>> ofLines()
      返回一个BodyHandler<Stream<String>>,该方法返回一个BodySubscriber<Stream<String>>,从BodySubscribers.ofLines(charset)获得。用于解码响应体字节的charset是根据HTTP响应头中由ofString()指定的方式获取的,并且行以BufferedReader.readLine()的方式分隔。

      当返回HttpResponse对象时,正文可能尚未完全接收。

      返回:
      一个响应体处理程序
    • ofByteArrayConsumer

      public static HttpResponse.BodyHandler<Void> ofByteArrayConsumer(Consumer<Optional<byte[]>> consumer)
      返回一个BodyHandler<Void>,该方法返回一个BodySubscriber<Void>,从BodySubscribers.ofByteArrayConsumer(Consumer)获得。

      当返回HttpResponse对象时,正文已完全写入消费者。

      API注释:
      此处理程序返回的订阅者不受流控制。因此,提供的消费者必须能够及时处理传递的任何数据量。
      参数:
      consumer - 用于接受响应体的消费者
      返回:
      一个响应体处理程序
    • ofByteArray

      public static HttpResponse.BodyHandler<byte[]> ofByteArray()
      返回一个BodyHandler<byte[]>,该方法返回一个BodySubscriber<byte[]>,从BodySubscribers.ofByteArray()获得。

      当返回HttpResponse对象时,正文已完全写入字节数组。

      返回:
      一个响应体处理程序
    • ofString

      public static HttpResponse.BodyHandler<String> ofString()
      返回一个BodyHandler<String>,该方法返回一个BodySubscriber<String>,从BodySubscribers.ofString(Charset)获得。使用在Content-Type响应头中指定的字符集对正文进行解码。如果没有这样的头,或者字符集不受支持,则使用UTF_8

      当返回HttpResponse对象时,正文已完全写入字符串。

      返回:
      一个响应体处理程序
    • ofPublisher

      public static HttpResponse.BodyHandler<Flow.Publisher<List<ByteBuffer>>> ofPublisher()
      返回一个BodyHandler<Publisher<List<ByteBuffer>>>,该方法创建一个BodySubscriber<Publisher<List<ByteBuffer>>>,从BodySubscribers.ofPublisher()获得。

      当返回HttpResponse对象时,响应头将完全读取,但正文可能尚未完全接收。 HttpResponse.body()方法返回一个Publisher<List<ByteBuffer>>,可以从中获取正文响应字节,因为它们被接收。发布者只能订阅一次。

      API注释:
      有关更多信息,请参见HttpResponse.BodySubscribers.ofPublisher()
      返回:
      一个响应体处理程序
    • buffering

      public static <T> HttpResponse.BodyHandler<T> buffering(HttpResponse.BodyHandler<T> downstreamHandler, int bufferSize)
      返回一个BodyHandler,当调用时,返回一个缓冲BodySubscriber,在将数据传递给下游订阅者之前对数据进行缓冲。通过调用BodySubscribers.buffering创建这些BodySubscriber实例,使用给定的下游处理程序和bufferSize参数。
      类型参数:
      T - 响应体类型
      参数:
      downstreamHandler - 下游处理程序
      bufferSize - 传递给BodySubscribers.buffering的缓冲区大小参数
      返回:
      一个正文处理程序
      抛出:
      IllegalArgumentException - 如果bufferSize <= 0