我打开一些带有表单的标签,当我按下命令按钮时(会话过期一段时间后),我收到一条java脚本警告说:
serverError:class javax.faces.application.ViewExpiredException viewId:/register.xhtml - 无法恢复视图/register.xhtml。
on firefox(本地glassfish 4)
我已添加:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/index.xhtml?faces-redirect=true</location>
</error-page>
在我的web.xml
中,但我没有重定向到我的索引。那是为什么?
编辑示例按钮
<h:commandButton value="Register" action="#{userController.register}">
<f:ajax execute="@form" render="@form" />
</h:commandButton>
UserController是ViewScoped
答案 0 :(得分:2)
如果你看一下JSF-2.2 spec的第13.3.6.3和13.3.6.4节,这是预期的行为,至少如果你有
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
在你的web.xml
中(它默默地忽略生产模式中的错误)。单击该按钮并接收
<error>
<error-name>...</error-name>
<error-message>...</error-message>
</error>
在回复中使用ViewExpiredException
。然后,客户端代码将对该错误信息做出反应。使用onerror
(在f:ajax
标记上)或addOnError
(在jsf.ajax
对象上)注册一个函数,以便自己处理错误。
由于很多人都希望服务器在这样的问题上指导客户端,所以omnifaces包括基本上重置你的响应的FullAjaxExceptionHandler并发送你指定的错误页面。
另见:
Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request
答案 1 :(得分:0)
尝试使用此方法来处理视图过期: 在项目中创建以下2个类
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;
public class ViewExpiredExceptionExceptionHandlerFactory extends
ExceptionHandlerFactory {
private ExceptionHandlerFactory parent;
public ViewExpiredExceptionExceptionHandlerFactory(
ExceptionHandlerFactory parent) {
this.parent = parent;
}
@Override
public ExceptionHandler getExceptionHandler() {
return new ViewExpiredExceptionExceptionHandler(
parent.getExceptionHandler());
}
}
和
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,
"/index");
facesContext.renderResponse();
} finally {
i.remove();
}
}
}
// At this point, the queue will not contain any ViewExpiredEvents.
// Therefore, let the parent handle them.
getWrapped().handle();
}
}
在faces-config.xml中添加以下行:
<factory>
<exception-handler-factory>path.to.class.ViewExpiredExceptionExceptionHandlerFactory</exception-handler-factory>
就是这样,你很高兴。
修改强>
好吧,我忘记了Omnifaces这样做的方式,我没有使用它,因为一旦你设置了错误页面,它会警告你为404制作页面而另一个我不记得的页面马上。您应该在faces-config.xml中添加以下内容:
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
你的代码会起作用。 有关更多信息,请参阅omnifaces网站http://showcase.omnifaces.org/exceptionhandlers/FullAjaxExceptionHandler;jsessionid=sOwX0FVqcY-InUhvDWEMksfQ中的FullAjaxExceptionHandlerFactory展示。
不要忘记在项目中添加所需的jar。