java - 如果在响应中返回 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 是否真的需要由我手动关闭?服务器不处理吗?如果应该是,那么推荐的方法是什么?
解决方案
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] 这里没有问题。任何使用的短绒工具都必须有一个容易逃生的舱口,否则不应该使用。
推荐阅读
- r - 在 R 中绘制宾夕法尼亚县的热图
- geb - 在 Geb 中指定多个环境
- django - Django:不支持的操作数类型 - :'NoneType'和'NoneType'
- google-sheets - 具有多个条件的 ARRAYFORMULA 总和
- python - 遍历字符串列表并替换某些字符
- java - 匿名内部类的 ClassName 相同 - obj.getClass().getName()
- python - 张量流中通过 3D 张量乘法得到的 3D 张量的形状是什么?
- python - html decode('utf-8') csv 双行 (python 3)
- yii2 - Yii 2 GridView 在 ActiveForm 中搜索
- android - 删除按钮在另一个布局中,如何从另一个布局中调用它