4

我知道在 getter 和 setter 中编写业务逻辑是一种非常糟糕的编程习惯,但是如果响应已经提交,有没有办法处理异常?

“响应已提交”和“标头已发送到客户端”究竟是什么意思?

4

2 回答 2

16

如果响应已经提交,则没有很好的方法来处理异常。HTTP 响应基本上由标头和正文组成。标头基本上指示客户端(网络浏览器)它应该如何准确地处理响应,例如内容类型、内容长度、字符编码、正文编码、缓存指令等。

您可以在 webbrowser 的开发人员工具集的 HTTP 流量监视器中看到标头。在 Chrome/IE9+/Firefox23+ 中按 F12 并检查“网络”选项卡。下面的屏幕显示是我的 Chrome 在您当前的问题上显示的内容:

在此处输入图像描述

(注意:“响应”选项卡显示响应正文)

响应正文是实际内容,通常是一堆 HTML 代码。服务器通常有一个固定大小的缓冲区来写入响应。缓冲区大小取决于服务器品牌/版本和配置,通常为 2KB~10KB。如果这个缓冲区溢出,那么它将被刷新到连接的另一端,客户端。这是响应的提交。客户端已经获得了响应的第一部分,通常已经代表了整组标头,也可能是正文的一部分。

响应的提交是不归路的。服务器无法取回已经发送的字节。更改响应标头为时已晚(例如,重定向基本上由Location标头指示,其中包含新 URL),更不用说响应正文了。您可以做的最好的事情是将错误信息附加到已经编写的响应正文中。但这可能会导致一些看起来很奇怪的 HTML,因为此时不知道哪些 HTML 标记需要关闭。浏览器可能无法以正确的方式呈现它。

除了避免 getter 中的业务逻辑以便在呈现响应时不会引发异常之外,避免已提交响应的另一种方法是将响应缓冲区大小配置为与 webapp 可以服务的最大页面一样大。如何做到这一点取决于服务器的品牌/版本。例如,在 Tomcat 中,您可以将其配置为element的bufferSize属性<Connector>flush()请注意,如果您自己的代码(隐式)调用响应输出流,这不会阻止刷新。

于 2013-01-18T10:51:44.223 回答
3

很好的解释 BalusC,我要补充一点,primefaces 在他们的异常处理程序中存在问题。他们尝试在请求已经提交后重定向到错误页面。正如你所说,我发现的唯一解决方案是在响应正文中添加一些额外的内容。我 owerride 处理程序并添加此代码

 if ( extContext.isResponseCommitted() ) {
            PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();
            writer.startElement( "script", null );
            writer.write( "window.location.href = '" + errorPageUrl + "';" );
            writer.endElement( "script" );
            writer.getWrapped().endCDATA();
            writer.endElement( "update" );
            writer.getWrapped().endDocument();
        }
        else {
            extContext.redirect( errorPageUrl );
            context.responseComplete();
        }
于 2015-02-03T13:03:13.390 回答