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,这将重新打开HttpOutputinclude()中使用,然后再次将其关闭。

一旦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)以指示此特定情况并中止连接,从而破坏了您可能想要的任何连接持久性。

08-06 13:22