I know writing business logic in getters and setters is a very bad programming practice,但是如果响应已经提交,有没有办法处理异常?
“已经提交的响应”和“标题已经发送给客户”的含义究竟是什么?
答案 0 :(得分:13)
如果响应已经提交,则没有很好的方法来处理异常。 HTTP响应基本上存在标题和正文。标题基本上指示客户端(webbrowser)应该如何处理响应,例如内容类型,内容长度,字符编码,正文编码,缓存指令等。
您可以在webbrowser的开发人员工具集的HTTP流量监视器中看到标头。在Chrome / IE9 + / Firefox23 +中按F12,然后选中“网络”标签。以下屏幕显示是我的Chrome在您当前的问题上显示的内容:
(注意:“响应”标签显示响应正文)
响应正文是实际内容,通常是一堆HTML代码的味道。服务器通常有一个固定大小的缓冲区来写响应。缓冲区大小取决于服务器品牌/版本和配置,通常为2KB~10KB。如果此缓冲区溢出,则它将刷新到连接的另一端即客户端。这是响应的提交。客户端已经获得了响应的第一部分,通常已经代表了整个标题集,也可能是正文的一部分。
提交回复是一个不归路。服务器无法恢复已发送的字节。更改响应标头为时已晚(例如,重定向基本上由Location
标头指示,其中包含新URL),更不用说响应主体了。最好的办法是将错误信息附加到已写入的响应正文中。但这可能最终出现在一些奇怪的HTML中,因为不知道哪个HTML标签需要在那时关闭。浏览器可能无法以正确的方式呈现它。
除了避免getter中的业务逻辑以便在呈现响应时不抛出异常,避免已提交响应的另一种方法是将响应缓冲区大小配置为与webapp可以服务的最大页面一样大。如何做到这一点取决于服务器make / version。例如,在Tomcat中,您可以将其配置为bufferSize
attribute of the <Connector>
element。请注意,如果您自己的代码(隐式)在响应输出流上调用flush()
,则这不会阻止刷新。
答案 1 :(得分:3)
好的exlanation BalusC和我会补充说,primefaces在他们的异常处理程序中有一个问题。他们在提交请求后尝试重定向到错误页面。正如您所说,我找到的唯一解决方案是向响应主体添加一些额外的内容。我强制处理程序并添加此代码
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();
}