ServletOutputStream.isReady()
javadoc says the following :
Returns: true if a write to this ServletOutputStream will succeed, otherwise returns false.
尽管 Jetty 的 ServletOutputStream
实现,当流处于 CLOSED
状态时,HttpOutput
似乎表现得相当困惑。它返回true
:
case CLOSED:
return true;
来源:HttpOutput.java:1011 .
此外,HttpOutput
中的所有三个 write
方法在 CLOSED
时都会抛出 EofException
:
case CLOSED:
throw new EofException("Closed");
看来 write 永远不可能成功。这种行为背后的原因是什么?
最佳答案
关键事实:关闭调用意味着写入操作。
CLOSED 内部状态表示该流/输出的使用对该调度而言已关闭(并非流本身实际上已关闭)。
我们是如何进入这种状态的?某些内容触发了 ServletOutputStream.close()
(进而触发 HttpOutput.close()
),现在不允许从当前调度对该流进行更多写入操作。
在 CLOSED 状态下,会发生刷新。
- 刷新将提交响应
- 刷新将完成对交换/连接/输出各层上存在的各种缓冲区的写入。
- 如果存在聚合缓冲区(用于许多小写入),则会将其写出。
- 如果有压缩层 (gzip),它也会从那里强制刷新。
- 然后所有这些缓冲区也会经过
传输编码
层(例如:分块)。 - 然后发生网络写入。
HttpOutput
也是所有嵌套请求的输出点,例如使用 RequestDispatcher
中的 include()
,这将重新打开HttpOutput
在 include()
期间使用,然后再次关闭它。
一旦HttpOutput
完全刷新/完成(不再调度,不再写入等),则最终缓冲区刷新完成,传输编码完成,HttpOutput被重置,回收,返回到HttpConnection,供下次交换使用。
我们可以在代码库中更好地进行 javadoc,或者至少使用更有意义的常量和变量名称。
已打开https://github.com/eclipse/jetty.project/issues/2687
关于写入时的 Jetty EofException
(不是 JVM EOFException
)。
一旦 ServletOutputStream
关闭以供特定调度使用,进一步调用 write()
将导致 Jetty EofException
。
还有一种 EofException
类型,您提交的响应详细信息被违反。
例如:您声明了一个 40MB 的响应 Content-Length
,但写入了 41MB,您超出了该提交响应的能力,这是一个 IOException。 Servlet 规范告诉我们在这种情况下抛出 IOException
。
Jetty 将抛出 Jetty 内部 EofException
(它扩展了 IOException)来指示此特定场景并中止连接,从而破坏您可能想要的任何连接持久性。
关于java - isReady() 在关闭状态下返回 true - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51101088/