【问题标题】:Does InputStream need to be closed if it's returned in a Response?如果在响应中返回 InputStream 是否需要关闭?
【发布时间】:2021-12-12 20:22:45
【问题描述】:

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

@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,我真的需要手动关闭它吗?服务器不处理吗? 如果应该是,那么推荐的方法是什么?

【问题讨论】:

  • 在这种情况下,您不能关闭流,因为任何处理 Response 对象并将实际结果写入 HTTP 连接的东西都无法从中读取.所以在这种情况下,声纳报告了误报。

标签: java resteasy java-ws


【解决方案1】:

Streaming 应该由 MessageBodyWriter 实现关闭。 如果您想在这里清楚 - 将您的流读取到字节数组并将其作为实体传递给响应。

See here similar question

【讨论】:

    【解决方案2】:

    按照 java 的设置方式,linting 工具不可能可靠地识别此等式的任一侧。具体来说:

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

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

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

    结论:Linter 是工具;提醒您查看代码的简化。盲目应用它告诉您的内容是愚蠢,并导致糟糕的代码。不要那样做。同义反复,任何你不能随便告诉 linter 关闭的 linting 工具都是一个坏工具,你应该立即停止使用它。

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

    回顾一下:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-10
      • 2022-12-14
      • 1970-01-01
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多