Java 包装体订户<;输入流>;在GZIPInputStream中,流导致挂起
我正在使用新的Java 包装体订户<;输入流>;在GZIPInputStream中,流导致挂起,java,gzipinputstream,java-http-client,Java,Gzipinputstream,Java Http Client,我正在使用新的java.net.http类来处理异步http请求+响应交换,并试图找到一种方法让BodySubscriber处理不同的编码类型,例如gzip 但是,映射bodysubscriber,使基础流被gzip输入流包装(当在响应头中找到“Content Encoding:gzip”时),会导致挂起。没有例外,只是完全停止活动 映射BodySubscriber的代码如下所示: private HttpResponse.BodySubscriber<InputStream> gz
java.net.http
类来处理异步http请求+响应交换,并试图找到一种方法让BodySubscriber处理不同的编码类型,例如gzip
但是,映射bodysubscriber
,使基础流被gzip输入流
包装(当在响应头中找到“Content Encoding:gzip”时),会导致挂起。没有例外,只是完全停止活动
映射BodySubscriber
的代码如下所示:
private HttpResponse.BodySubscriber<InputStream> gzippedBodySubscriber(
HttpResponse.ResponseInfo responseInfo) {
return HttpResponse.BodySubscribers.mapping(
HttpResponse.BodySubscribers.ofInputStream(),
this::decodeGzipStream);
}
private InputStream decodeGzipStream(InputStream gzippedStream) {
System.out.println("Entered decodeGzipStream method.");
try {
InputStream decodedStream = new GZIPInputStream(gzippedStream);
System.out.println(
"Created GZIPInputStream to handle response body stream.");
return decodedStream;
} catch (IOException ex) {
System.out.println("IOException occurred while trying to create GZIPInputStream.");
throw new UncheckedIOException(ex);
}
}
private-HttpResponse.BodySubscriber gzip-BodySubscriber(
HttpResponse.ResponseInfo(响应信息){
返回HttpResponse.BodySubscribers.mapping(
HttpResponse.BodySubscribers.ofInputStream(),
这个::decodeGzipStream);
}
专用InputStream decodeGzipStream(InputStream GzipEdStream){
System.out.println(“输入解码流方法”);
试一试{
InputStream decodedStream=新的GZIPInputStream(gzippedStream);
System.out.println(
“创建了GZIPInputStream来处理响应体流。”);
返回解码流;
}捕获(IOEX异常){
System.out.println(“尝试创建GZIPInputStream时发生IOException。”);
抛出新的未选中异常(ex);
}
}
接收到具有“gzip”编码的HTTP响应将导致控制台显示以下内容:
输入EncodedBodyHandler.apply方法。输入decodeGzipStream方法 没有看到更多内容,因此永远不会执行调用
GZIPInputStream
构造函数后的行
有人知道为什么将BodySubscriber
中的InputStream
包装到GZIPInputStream
中的尝试挂起了吗
注意:未编码(原始文本)HTTP响应正文的等效方法只包含对
BodySubscribers.ofInputStream()
的调用,无需任何映射,这样就可以毫无问题地接收和显示响应。遇到了完全相同的问题。我在Javadoc中尝试了BodySubscribers.mapping
方法的示例。同样的行为,应用程序挂起时没有任何错误
这可能是一个bug,因为这是来自Javadoc的官方示例
public static <W> BodySubscriber<W> asJSON(Class<W> targetType) {
BodySubscriber<InputStream> upstream = BodySubscribers.ofInputStream();
BodySubscriber<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;
} }
publicstaticbodysubscriber asJSON(类targetType){
BodySubscriber上游=BodySubscribers.ofInputStream();
BodySubscriber下游=BodySubscribers.mapping(
上游
(输入流是)->{
try(InputStream=is){
ObjectMapper ObjectMapper=新的ObjectMapper();
返回objectMapper.readValue(流,targetType);
}捕获(IOE异常){
抛出新的未选中异常(e);
}
});
返回下游;
} }
这确实是一个bug。我已经登录了。我可以建议两种解决方法:
解决方案一
不要使用BodySubscribers.mapping
——而是在获取HttpResponse的主体后,将InputStream
转换为GZIPInputStream
:
GZIPInputStream gzin = new GZIPInputStream(resp.getBody());
解决方案二
让映射函数返回一个Supplier
,注意在调用Supplier::get
之前不要创建gziInputStream
static final class ISS implements Supplier<InputStream> {
final InputStream in;
GZIPInputStream gz;
ISS(InputStream in) {
this.in = in;
}
public synchronized InputStream get() {
if (gz == null) {
try {
gz = new GZIPInputStream(in);
} catch (IOException t) {
throw new UncheckedIOException(t);
}
}
return gz;
}
}
静态最终类ISS实现供应商{
最终输入流输入;
gzip输入流gz;
ISS(输入流输入){
this.in=in;
}
公共同步InputStream get(){
if(gz==null){
试一试{
gz=新的GZIPInputStream(in);
}捕获(IOT异常){
抛出新的未选中异常(t);
}
}
返回gz;
}
}
注意:如果有人知道如何格式化上面的代码片段,我将不胜感激。单击编辑器上的{}按钮似乎不起作用。似乎编号列表内容对代码示例不起作用,因此我将编号列表替换为标题部分。(请随意编辑标题以提供更具描述性的名称。)顺便说一句,最后我使用了新的gzip输入流(response.getBody())
解决方法,如.Ah。。。谢谢你的信息!下次我会记住的:-)