- 封装接口:
-
HttpResponse<T>
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 Summary
Modifier and TypeMethodDescriptionstatic <T> HttpResponse.BodySubscriber
<T> buffering
(HttpResponse.BodySubscriber<T> downstream, int bufferSize) 返回一个BodySubscriber
,在将数据传递给给定的下游订阅者之前对数据进行缓冲。static HttpResponse.BodySubscriber
<Void> 返回一个响应订阅者,用于丢弃响应体。static HttpResponse.BodySubscriber
<Void> fromLineSubscriber
(Flow.Subscriber<? super String> subscriber) 返回一个将所有响应体逐行转发给给定Flow.Subscriber
的body订阅者。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订阅者。static HttpResponse.BodySubscriber
<Void> fromSubscriber
(Flow.Subscriber<? super List<ByteBuffer>> subscriber) 返回一个将所有响应体逐行转发给给定Flow.Subscriber
的body订阅者。static <S extends Flow.Subscriber<? super List<ByteBuffer>>,
T>
HttpResponse.BodySubscriber<T> fromSubscriber
(S subscriber, Function<? super S, ? extends T> finisher) 返回一个将所有响应体逐行转发给给定Flow.Subscriber
的body订阅者。static <T,
U> HttpResponse.BodySubscriber <U> mapping
(HttpResponse.BodySubscriber<T> upstream, Function<? super T, ? extends U> mapper) 返回一个BodySubscriber
,其响应体值为将给定函数应用于给定upstream
BodySubscriber
的body对象的结果。static HttpResponse.BodySubscriber
<byte[]> 返回一个将响应体存储为字节数组的BodySubscriber
。static HttpResponse.BodySubscriber
<Void> ofByteArrayConsumer
(Consumer<Optional<byte[]>> consumer) 返回一个将传入的响应体数据提供给Optional<byte[]>
的Consumer的BodySubscriber
。static HttpResponse.BodySubscriber
<Path> 返回一个将响应体存储在以给定名称打开的文件中的BodySubscriber
。static HttpResponse.BodySubscriber
<Path> ofFile
(Path file, OpenOption... openOptions) 返回一个将响应体存储在以给定选项和名称打开的文件中的BodySubscriber
。返回一个将响应体作为InputStream
流式传输的BodySubscriber
。static HttpResponse.BodySubscriber
<Stream<String>> 返回一个通过Publisher<List<ByteBuffer>>
发布响应体的响应订阅者。static HttpResponse.BodySubscriber
<String> 返回一个将响应体存储为使用给定Charset
转换的String
的BodySubscriber
。static <U> HttpResponse.BodySubscriber
<U> replacing
(U value) 返回一个响应订阅者,用于丢弃响应体。
-
Method Details
-
fromSubscriber
public static HttpResponse.BodySubscriber<Void> fromSubscriber(Flow.Subscriber<? super List<ByteBuffer>> subscriber) - API 注释:
-
此方法可用作
BodySubscriber
和Flow.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订阅者的完成阶段在给定的订阅者的onComplete
或onError
中的一个被调用后完成。给定的
finisher
函数在给定订阅者的onComplete
被调用后应用。finisher
函数与给定的订阅者一起调用,并返回一个作为响应体设置的值。- API 注释:
-
此方法可用作
BodySubscriber
和Flow.Subscriber
之间的适配器。 - 类型参数:
-
S
- 订阅者的类型 -
T
- 响应体的类型 - 参数:
-
subscriber
- 订阅者 -
finisher
- 在订阅者完成后应用的函数 - 返回:
- 一个body订阅者
-
fromLineSubscriber
public static HttpResponse.BodySubscriber<Void> fromLineSubscriber(Flow.Subscriber<? super String> subscriber) 返回一个将所有响应体逐行转发给给定Flow.Subscriber
的body订阅者。返回的body订阅者的完成阶段在给定的订阅者的onComplete
或onError
中的一个被调用后完成。字节使用UTF-8
字符集进行解码,行以BufferedReader.readLine()
的方式分隔。- API 注释:
-
此方法可用作
BodySubscriber
和Flow.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订阅者的完成阶段在给定的订阅者的onComplete
或onError
中的一个被调用后完成。给定的
finisher
函数在给定订阅者的onComplete
被调用后应用。finisher
函数与给定的订阅者一起调用,并返回一个作为响应体设置的值。- API 注释:
-
此方法可用作
BodySubscriber
和Flow.Subscriber
之间的适配器。 - 类型参数:
-
S
- 订阅者的类型 -
T
- 响应体的类型 - 参数:
-
subscriber
- 订阅者 -
finisher
- 在订阅者完成后应用的函数 -
charset
- 用于解码字节的Charset
-
lineSeparator
- 可选的行分隔符:可以为null
,在这种情况下,行将以BufferedReader.readLine()
的方式分隔。 - 返回:
- 一个body订阅者
- 抛出:
-
IllegalArgumentException
- 如果提供的lineSeparator
是空字符串
-
ofString
- 参数:
-
charset
- 用于转换字符串的字符集 - 返回:
- 一个body订阅者
-
ofByteArray
返回一个将响应体存储为字节数组的BodySubscriber
。使用此订阅者的
HttpResponse
在整个响应读取完毕后可用。- 返回:
- 一个body订阅者
-
ofFile
返回一个BodySubscriber
,将响应体存储在使用给定选项和名称打开的文件中。文件将在读取响应体之前使用FileChannel.open
打开。任何抛出的异常将从HttpClient::send
或HttpClient::sendAsync
中返回或抛出。使用此订阅器的
HttpResponse
在整个响应读取完成后可用。在默认文件系统提供程序的情况下,在创建
BodySubscriber
时将执行安全管理器权限检查。否则,可能会在文件访问时异步执行权限检查。必须注意不要将BodySubscriber
与不受信任的代码共享。- 参数:
-
file
- 要存储响应体的文件 -
openOptions
- 打开文件时要使用的选项列表 - 返回:
- 一个body订阅器
- 抛出:
-
IllegalArgumentException
- 如果指定了无效的打开选项集 -
SecurityException
- 在默认文件系统提供程序的情况下,并且安装了安全管理器,将调用checkWrite
来检查对给定文件的写访问权限
-
ofFile
返回一个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
返回一个BodySubscriber
,将响应体作为InputStream
流式传输。使用此订阅器的
HttpResponse
在读取响应头后立即可用,无需等待整个响应体被处理。然后可以直接从InputStream
中读取响应体。- API 注意:
-
为确保释放与相应交换相关的所有资源,调用方必须确保要么读取所有字节直到达到EOF,要么在无法或不愿这样做时调用
InputStream.close()
。在耗尽流之前调用close
可能会导致底层HTTP连接被关闭,并阻止其被用于后续操作。 - 实现注意:
-
由此方法的默认实现返回的
InputStream
的read
方法在阻塞读取时如果线程被中断将抛出一个带有线程中断状态设置的IOException
。在这种情况下,请求也将被取消,并且InputStream
将被关闭。 - 返回:
-
一个将响应体作为
InputStream
流式传输的body订阅器。
-
ofLines
返回一个BodySubscriber
,将响应体作为Stream
<String>
流式传输,流中的每个字符串对应于由BufferedReader.lines()
定义的一行。使用此订阅器的
HttpResponse
在读取响应头后立即可用,无需等待整个响应体被处理。然后可以直接从Stream
中读取响应体。- API 注意:
-
为确保释放与相应交换相关的所有资源,调用方必须确保要么读取所有行直到流耗尽,要么在无法或不愿这样做时调用
BaseStream.close()
。在耗尽流之前调用close
可能会导致底层HTTP连接被关闭,并阻止其被用于后续操作。 - 参数:
-
charset
- 将字节转换为字符时要使用的字符集 - 返回:
-
一个将响应体作为
Stream
<String>
流式传输的body订阅器。 - 参见:
-
ofPublisher
返回一个响应订阅器,通过Publisher<List<ByteBuffer>>
发布响应体字节。使用此订阅器的
HttpResponse
在读取响应头后立即可用,无需等待整个响应体被处理。然后可以通过订阅HttpResponse
的body
方法返回的发布者获取响应体字节。通过
HttpResponse
的body
方法返回的发布者只能订阅一次。第一个订阅者将在成功订阅时接收响应体字节,否则将导致订阅被取消。如果尝试进行更多订阅,则后续订阅者将立即被订阅为空订阅,并且它们的onError
方法将使用IllegalStateException
调用。- API 注意:
-
为确保释放与相应交换相关的所有资源,调用方必须确保提供的发布者只订阅一次,并且要么请求所有字节直到
onComplete
或onError
被调用,要么取消提供的订阅。请注意,根据用于交换的实际HTTP协议版本,取消订阅而不是耗尽流可能会导致底层HTTP连接被关闭,并阻止其被用于后续操作。 - 返回:
-
一个通过
Publisher<List<ByteBuffer>>
发布响应体字节的BodySubscriber
。
-
replacing
返回一个响应订阅器,丢弃响应体。提供的值是从HttpResponse.body()
返回的值。- 类型参数:
-
U
- 响应体的类型 - 参数:
-
value
- 从HttpResponse.body()返回的值,可以为null
- 返回:
-
一个
BodySubscriber
-
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
- 映射函数 - 返回:
- 一个映射体订阅者
-