Java 处理';会话已过期';在JSF web应用程序中,在JBoss AS 5中运行

Java 处理';会话已过期';在JSF web应用程序中,在JBoss AS 5中运行,java,session,jsf,servlet-filters,viewexpiredexception,Java,Session,Jsf,Servlet Filters,Viewexpiredexception,这项质询与我的另一项质询有关。下面是我要做的: 我有一个JSFWeb应用程序在JBossAS5上运行 当用户处于非活动状态(例如15分钟)时,如果他在会话过期后试图使用该应用程序,我需要注销该用户并将其重定向到登录页面 因此,正如在“”中所建议的,我实现了一个过滤器,它检查会话过期的条件,并在会话过期时将用户重定向到session-timed-out.jsp页面 我在web.xml中的所有其他过滤器定义之上添加了SessionExpiryCheckFilter,因此我的会话到期检查总是第一个命中

这项质询与我的另一项质询有关。下面是我要做的:

  • 我有一个JSFWeb应用程序在JBossAS5上运行
  • 当用户处于非活动状态(例如15分钟)时,如果他在会话过期后试图使用该应用程序,我需要注销该用户并将其重定向到登录页面
  • 因此,正如在“”中所建议的,我实现了一个过滤器,它检查会话过期的条件,并在会话过期时将用户重定向到session-timed-out.jsp页面
  • 我在web.xml中的所有其他过滤器定义之上添加了SessionExpiryCheckFilter,因此我的会话到期检查总是第一个命中
  • 现在是我面临的挑战。由于我使用的是JBoss AS,当会话过期时,JBoss会自动将我重定向到登录页面(请注意,不会调用会话过期检查过滤器)。因此,在我登录之后,我的SessionExpiryCheckFilter会截获请求,并看到会话可用。但是,它抛出异常
    javax.faces.application.ViewExpiredException:viewId:/mypage.faces-View/mypage.faces无法还原。


    以前有人遇到过这个问题吗?有什么办法可以解决这个问题吗?

    我建议结合过滤器编写一个会话侦听器

    会话到期时,您可以创建新的会话对象,并在新对象上设置超时值

    只需检查过滤器中的超时值并重定向浏览器即可


    请参见

    以下方法适用于我。请注意,您必须使用JSTL核心标记库重定向,而不是jsp重定向才能工作(因为jsp也会过期)

    FacesConfig.xml中,您可以放置以下内容:

    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/sessionExpired.jsf</location>
    </error-page>
    
    
    javax.faces.application.ViewExpiredException
    /sessionExpired.jsf
    
    sessionExpired.jsp

    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
    <c:redirect url="/login.jsf" />
    
    
    
    您还可以将此方法用于其他错误类型或异常。例如,元素包含错误代码或异常类型与web应用程序中资源路径之间的映射:

    <error-page>
        <error-code>400</error-code>
        <location>/400.html</location>
    </error-page>
    
    
    400
    /400.html
    
    或元素包含Java异常类型的完全限定类名

    <error-page>
        <exception-type>javax.servlet.ServletException</exception-type>
        <location>/servlet/ErrorDisplay</location>
    </error-page>
    
    
    javax.servlet.ServletException
    /servlet/ErrorDisplay
    
    如果您使用的是Mojarra/Sun RI,您可能希望尝试将其添加到web.xml中:

    <context-param>
        <param-name>com.sun.faces.enableRestoreView11Compatibility</param-name> 
        <param-value>true</param-value>
    </context-param>
    
    
    com.sun.faces.enableRestoreView11兼容性
    真的
    

    但是,请注意,这并不总是完美的解决方案。它隐藏了用户丢失会话的事实

    为还原视图实现javax.faces.event.PhaseListener

    @Override
    public void afterPhase(PhaseEvent event) {
        FacesContext facesContext = event.getFacesContext();
         if(facesContext.getViewRoot()==null){   
           try{   
               facesContext.getExternalContext().redirect(HOME_PAGE);   
               facesContext.responseComplete();   
           } catch (IOException e){   
               e.printStackTrace();   
           }   
         }
    }
    
    @Override
    public void beforePhase(PhaseEvent event) {}
    
    @Override
    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }
    

    在faces config.xml中注册我试着为它编写一个过滤器,但是它对我不起作用,所以我做了一个 替代它

    我在不希望用户不登录就访问的每个页面中都这样做:

    <f:view>
        <h:dataTable value="#{userHome.validuser()}"/>
         // my code
    <f:view/>
    

    如果有一个会话但没有人登录,那么它会将您带到重定向页面。

    您使用的是Facelet还是JSP?我使用的是Facelet-JBoss RichFacest这不是最好的解决方案。
    public void validuser()
    {
         FacesContext context = FacesContext.getCurrentInstance();
        UserLogin ul = (UserLogin) context.getExternalContext().getSessionMap().get("userbean");
    
         if (ul == null)
             try{
                    context.getExternalContext().redirect("/HIBJSF/faces/LoginPage.xhtml");
                    context.responseComplete();
            }
             catch (IOException e)
            {
             e.printStackTrace();
            }
    }