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