到目前为止,我遇到的所有ExceptionHandlerFactory
示例都会在发现viewExpired.jsf
时将用户重定向到ViewExpiredException
页面:
public class ViewExpiredExceptionExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
public ViewExpiredExceptionExceptionHandler(ExceptionHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public ExceptionHandler getWrapped() {
return this.wrapped;
}
@Override
public void handle() throws FacesException {
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
Throwable t = context.getException();
if (t instanceof ViewExpiredException) {
ViewExpiredException vee = (ViewExpiredException) t;
FacesContext facesContext = FacesContext.getCurrentInstance();
Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler();
try {
// Push some useful stuff to the request scope for use in the page
requestMap.put("currentViewId", vee.getViewId());
navigationHandler.handleNavigation(facesContext, null, "/viewExpired");
facesContext.renderResponse();
} finally {
i.remove();
}
}
}
// At this point, the queue will not contain any ViewExpiredEvents. Therefore, let the parent handle them.
getWrapped().handle();
}
}
在我看来,以下简单的web.xml
配置基本相同且简单得多:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/viewExpired.jsf</location>
</error-page>
这提示了一个问题 - 为什么会使用ExceptionHandlerFactory
?
答案 0 :(得分:24)
特定示例只做了一件有用的事情:它将视图ID保存为请求属性,以便您可以使用例如
<h:link value="Go back to previous page" outcome="#{currentViewId}" />
但这并不是非常有用,因为原始请求URI已由<error-page>
的默认请求属性javax.servlet.error.request_uri
提供。
<h:outputLink value="#{requestScope['javax.servlet.error.request_uri']}">Go back to previous page</h:outputLink>
然而,自定义ExceptionHandler
真正有用的一点是,它允许您在 ajax请求期间处理异常。默认情况下,他们在客户端没有任何形式的有用反馈。只有在项目阶段设置为“开发”的Mojarra中,您才会看到带有异常消息的简单JavaScript警报消息。但就是这样。 “生产”阶段没有单一形式的反馈。使用自定义ExceptionHandler
,您将能够解析web.xml
以查找错误页面位置,使用它创建新的UIViewRoot
并强制JSF将ajax渲染设置为@all
。
所以,基本上是:
String errorPageLocation = "/WEB-INF/errorpages/500.xhtml";
context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation));
context.getPartialViewContext().setRenderAll(true);
context.renderResponse();
另请参阅此相关问题:What is the correct way to deal with JSF 2.0 exceptions for AJAXified components?和此博客:Full Ajax Exception Handler。
答案 1 :(得分:3)
取决于ViewExpiredException
,你需要做什么。
如果您只想显示用户错误页面,可以按照说法进行操作。
此post向您展示如何以编程方式拦截
ViewExpiredException
并做一些不错的事情。