4

我用表单打开了一些选项卡,当我按下命令按钮时(会话过期一段时间后)我收到一个 java 脚本警报,说:

serverError: class javax.faces.application.ViewExpiredException viewId:/register.xhtml - 无法恢复视图 /register.xhtml。

在 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

4

2 回答 2

3

这是预期的行为,如果您查看JSF-2.2 规范的 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(它默默地忽略生产模式下的错误)。当您单击该按钮并接收到时,JSF 客户端代码会发送一个 AJAX 请求

<error>
    <error-name>...</error-name>
    <error-message>...</error-message>
</error>

与你ViewExpiredException的回应。然后期望客户端代码对该错误信息做出反应。onerror使用(在f:ajax标签上)或addOnError(在对象上)注册一个函数jsf.ajax来自己处理错误。

由于很多人希望服务器在此类问题上指导客户端,因此omnifaces 包含FullAjaxExceptionHandler,它基本上会重置您的响应并发送您指定的错误页面。

也可以看看:

JSF/PrimeFaces ajax 请求上的会话超时和 ViewExpiredException 处理

于 2014-02-18T10:37:17.000 回答
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 添加到您的项目中。

于 2014-02-17T09:49:49.620 回答