首页 > 解决方案 > 如果在响应中返回 InputStream 是否需要关闭?

问题描述

我有一段类似于这样的代码:

@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Path("test")
public Response getFileContent() {
    InputStream in = Files.newInputStream(filePath);
    return Response.ok(in,MediaType.APPLICATION_OCTET_STREAM);
}

Sonarcube 抱怨它没有包含在 try-with-resources 中。但是当我按照它的建议做时,当我尝试调用端点时,我会得到 java.nio.channels.ClosedChannelException 。

如果我在响应中返回 InputStream 是否真的需要由我手动关闭?服务器不处理吗?如果应该是,那么推荐的方法是什么?

标签: javaresteasyjava-ws

解决方案


java的设置方式,linting工具不可能可靠地识别这个等式的任何一边。具体来说:

  • 在给定任何方法或构造函数签名的情况下,不可能弄清楚调用者显然是关闭它的“责任”方。您可以获得的最接近的概念是调用实现 AutoClosable 的类型的构造函数暗示它(足够真实),但Files.newInputStream不是其中之一。您甚至不能使用: AutoClosable 类型的构造函数,或者返回这种类型并包含/以字母n, e,开头的方法w。毕竟,socket.getInputStream()是调用者应该关闭的资源,例如。在实践中,这些 linter 附带一个已知列表,因此,linter 可以而且经常是错误的。

  • 端点是否接管关闭职责也是未知的在这里,返回一个Response对象转移了责任;linter 不知道它,也没有标准系统知道它,除了建立一个这个 linter 显然没有做的巨大列表。

  • 甚至不知道资源是否代表通常应该关闭的东西,但在这种特定情况下不应该。教科书的例子是new Scanner(System.in)——除非 linter 有硬编码的异常,否则他们会告诉你应该关闭扫描仪,而这个建议是完全错误的。实际上,您不应该关闭该扫描仪;关闭它是损坏的代码。

结论:Linter 是工具;提醒您查看代码的简化。盲目地应用它告诉你的内容是愚蠢的,并且会导致糟糕的代码。不要那样做。那么,重言式的任何 linting 工具,如果你不能简单地告诉 linter 关闭,因为它是错误的,那么它是一个坏工具,你应该立即停止使用它。

注意:作为一个实用点,您可以只返回 Path 对象本身,即return Response.ok(filePath, MediaType.APPLICATION_OCTET_STREAM),resteasy 应该知道如何处理它。在不太可能发生的情况下,它filePath.toFile()肯定会起作用。但是,这在这里有效,但是在某些情况下,您所拥有的只是一个输入流。因此,该原则适用。

回顾一下:

[1] Linter 本质上通常是错误的。因此,要求此类工具的用户理解他们告诉您的内容仅仅是一个提示;在任何情况下都不应仅仅因为 linter 这么说就盲目地遵守 linter 的建议。

[2] 实际上不可能写出完美解决检测use-without-close代码错误问题的linter。

[3] 这里没有问题。任何使用的短绒工具都必须有一个容易逃生的舱口,否则不应该使用。


推荐阅读