[英]JSF 2.0 Custom Exception Handler throws IllegalStateException on handleNavigation
我为JSF编写了一个自定义异常处理程序来记录异常并导航到一个错误页面以显示给用户。 不幸的是,我得到了一个IllegalStateException“在提交响应之后无法调用sendRedirect()”在Handler中调用“handleNavigation”时。 任何想法,我做错了什么?
我的处理程序:
public class MyExceptionHandler extends ExceptionHandlerWrapper {
private Logger log = ...;
public ExceptionHandler wrappedHandler = null;
public MyExceptionHandler (ExceptionHandler wrappedHandler) {
this.wrappedHandler = wrappedHandler;
}
@Override
public ExceptionHandler getWrapped() {
return wrappedHandler;
}
@Override
public void handle() throws FacesException {
Iterator<ExceptionQueuedEvent> iter = null;
ExceptionQueuedEvent event = null;
ExceptionQueuedEventContext eventContext = null;
FacesContext facesContext = null;
iter = getUnhandledExceptionQueuedEvents().iterator();
while (iter.hasNext()) {
try {
event = iter.next();
eventContext = (ExceptionQueuedEventContext) event.getSource();
log.error("JSF Exception aufgetreten", eventContext.getException());
facesContext = FacesContext.getCurrentInstance();
// !!!!!!!! Exception occurs here !!!!!!!!!!!
facesContext
.getApplication()
.getNavigationHandler()
.handleNavigation(facesContext, null, "error");
facesContext.renderResponse();
} catch (RuntimeException ex) {
throw ex; // just to set break point
} finally {
iter.remove();
}
}
getWrapped().handle();
}
}
faces-config.xml中的导航定义
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>error</from-outcome>
<to-view-id>/faces/error.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
在呈现响应阶段,当HTTP响应已经提交时,显然已经抛出了正在处理的异常。 提交的响应意味着HTTP响应的第一部分(包括标头)已经发送到客户端。 这是一个不归路。 您无法从客户端返回已发送的字节。
当写入的内容超过缓冲区大小时,通常会自动提交响应,默认情况下通常为~2KB,具体取决于servletcontainer和Facelets配置。 平均HTML <head>
占用已经1~2KB。 因此,在JSF开始渲染<body>
或只是其中的一小部分之前,响应已经提交的变化很大。
在您的特定情况下,还有一个原因:当您收到多个未处理的异常时,您也会遇到麻烦,因为您在导航后没有中止while
循环,而是继续处理下一个异常。 您不能将多个响应(错误页面)返回到单个请求。 您应该收集所有异常并仅导航一次,或者在第一个之后中止循环。
在任何情况下,只有响应不是(自动)提交的,才能处理渲染响应期间抛出的异常。 您可以尝试多种方法来防止响应过早自动提交:
将Facelets缓冲区大小设置为最大HTML响应的大小。 例如64KB:
<context-param> <param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name> <param-value>65535</param-value><!-- 64KB --> </context-param>
在呈现视图之前执行异常敏感的业务作业(即,不要在GET请求期间构造的bean的(post)构造函数中执行此操作):
<f:event type="preRenderView" listener="#{bean.init}" />
至于在JSF中处理异常,您可能会发现OmniFaces FullAjaxExceptionHandler
很有帮助。 你可以在这里找到它的源代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.