【问题标题】:Session timeout is not working in JSF 2.0会话超时在 JSF 2.0 中不起作用
【发布时间】:2017-12-09 04:17:26
【问题描述】:

我是 JSF 2.0 / PrimeFaces 的新手,我使用 JSF 2.0 + Spring 4 创建了一个 webapp。对于会话超时,我在 web.xml 中完成了以下映射:

<session-config>
    <session-timeout>1</session-timeout>
</session-config>

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/resources/login/timeout.xhtml</location>
</error-page>

登录后,用户重定向到admin.xhtml,其中有元素为

<h:link value="showAnotherPage" outcome="other.xhtml"/>

但是 2 或 5 分钟后,当我点击链接时,它会将我重定向到 other.xhtml 页面而不是超时页面。

我有什么需要配置的吗?请帮忙。

【问题讨论】:

  • other.xhtml 是需要登录的受保护页面吗?你为什么要测试这个平台。注意这与 JSF 无关。它由 Tomcat 或任何您的 Servlet 容器强制执行。
  • @EJP : admin.xhtml 是我登录成功后显示的页面。我刚刚添加了一个链接来检查 admin.xhtml 上的会话超时是否有效。它不是任何受保护的页面。

标签: spring jsf primefaces spring-4


【解决方案1】:

我遇到了这个问题。您需要确保没有客户端调用轮询 (ajax) 服务器端资源,如果发生这种情况,会话将不会过期。我有一个&lt;p:poll /&gt; 标签,它不会让会话过期。

【讨论】:

    【解决方案2】:

    我会以另一种方式亲自实现它。

    在您的faces-config.xml 中定义一个异常处理程序工厂,如下所示:

    <factory>
        <exception-handler-factory>
            com.package.faces.FullAjaxExceptionHandlerFactory
        </exception-handler-factory>
    </factory>
    

    创建扩展javax.faces.context.ExceptionHandlerFactory 的异常处理程序工厂。它应该返回您自己的 ExceptionHandler 实现。这可能是一个例子:

    import javax.faces.context.ExceptionHandler;
    import javax.faces.context.ExceptionHandlerFactory;
    
    public class FullAjaxExceptionHandlerFactory extends ExceptionHandlerFactory {
    
        private ExceptionHandlerFactory wrapped;
    
        /**
         * Construct a new full ajax exception handler factory around the given wrapped factory.
         * @param wrapped The wrapped factory.
         */
        public FullAjaxExceptionHandlerFactory(ExceptionHandlerFactory wrapped) {
                this.wrapped = wrapped;
        }
    
        /**
         * Returns a new instance of {@link FullAjaxExceptionHandler} which wraps the original exception handler.
         */
        @Override
        public ExceptionHandler getExceptionHandler() {
                return new FullAjaxExceptionHandler(wrapped.getExceptionHandler());
        }
    
        /**
         * Returns the wrapped factory.
         */
        @Override
        public ExceptionHandlerFactory getWrapped() {
                return wrapped;
        }
    
    }
    

    最后,扩展javax.faces.context.ExceptionHandlerWrapper 来处理所有异常。一个例子如下:

    public class FullAjaxExceptionHandler extends ExceptionHandlerWrapper {
    
        private ExceptionHandler wrapped;
    
        public FullAjaxExceptionHandler(ExceptionHandler wrapped) {
            this.wrapped = wrapped;
        }
    
        private static Throwable extractCustomException(Throwable ex) {
            Throwable t = ex;
            while (t != null) {
                if (t instanceof YourOwnExceptionInterface) {
                    return t;
                }
                t = t.getCause();
            }
            return ex;
        }
    
        private static String extractMessage(Throwable t) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            t.printStackTrace(pw);
    
            return matchJmillErrorTag(sw.toString()); 
        }
    
        public static boolean handleException(Throwable original) {
            Throwable ex = extractCustomException(original);
    
            if (ex instanceof ViewExpiredException) {
                // redirect to login page
                return false;
            } else if (ex instanceof YourOwnExceptionInterface) {
                ((YourOwnExceptionInterface) ex).handle();
                return true;
            } else if (ex instanceof NonexistentConversationException) {
                FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
    
                // redirect to login page
    
                return false;
            } else {
                String message = extractMessage(ex);
                final FacesContext fc = FacesContext.getCurrentInstance();
                original.printStackTrace();
    
                // redirect to error page
    
                fc.responseComplete();
                return true;
            }
        }
    
        @Override
        public void handle() throws FacesException {
            final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
            FacesContext facesContext = FacesContext.getCurrentInstance();
            if (Redirector.isRedirectingToLogin(facesContext)) {
                return;
            }
            while (i.hasNext()) {
                ExceptionQueuedEvent event = i.next();
                ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
                i.remove();
                if (!handleException(context.getException())) {
                    return;
                }
            }
            getWrapped().handle();
        }
    
        @Override
        public ExceptionHandler getWrapped() {
            return wrapped;
        }
    
    }
    

    查看上一课的public static boolean handleException(Throwable original)。您可以使用它来管理所有异常。

    有一次我在那里设置了一个关于YourOwnExceptionInterface 的条件,它是一个带有handle() 方法的接口,例如我将通过NotAuthorizedException 类型的异常来实现。在这种情况下,在NotAuthorizedExceptionhandle() 方法中,我会通知用户他无法通过p:growl 组件完成某个操作。我会在我的 bean 中使用它作为 throw new NotAuthorizedException("message");

    自定义异常类当然应该扩展RuntimeException

    【讨论】:

    • 您会在应用程序中添加几码冗余代码,为什么?它如何解决问题?问题是什么?
    • 刚刚提出了一个我认为至少在大型(企业)应用程序中有用的解决方案。这种控制/定制对我的项目有很大帮助。正在解决的问题是如果抛出某个错误或异常,让用户访问某个页面。比如上面问的javax.faces.application.ViewExpiredException。这是我的解决方案。 @EJP 你为什么不写一个更好的?
    猜你喜欢
    • 1970-01-01
    • 2012-05-09
    • 2014-12-05
    • 1970-01-01
    • 2011-09-15
    • 2016-01-21
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多