我一直在看这个话题的很多帖子,但是无法得到一个适用于我的例子的解决方案.
我正在使用Java EE 6与JSF 2.0(部署在JBoss AS 7.1上)
在我的web.xml中,我有:
<session-config> <session-timeout>1</session-timeout> </session-config>
我试过了
方法1:使用过滤器
我尝试了以下过滤器:
@WebFilter() public class TimeOutFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException { System.out.println("filter called"); final HttpServletRequest req = (HttpServletRequest) request; final HttpSession session = req.getSession(false); if (session != null && !session.isNew()) { chain.doFilter(request,response); } else { System.out.println("Has timed out"); req.getRequestDispatcher("/logon.xthml").forward(request,response); } } @Override public void destroy() { } }
在web.xml我尝试过
<filter-mapping> <filter-name>TimeOutFilter</filter-name> <url-pattern>*.xhtml</url-pattern> </filter-mapping>
和
<filter-mapping> <filter-name>TimeOutFilter</filter-name> <servlet-name>Faces Servlet</servlet-name> </filter-mapping>
过滤器的工作原理是每个请求(在控制台中记录“fiter called”).但是当会话超时时,它不会被调用.
方法2:HttpSessionLister
我试图使用一个HttpSessionListerner.该方法称为具有以下签名:
public void sessionDestroyed(HttpSessionEvent se) { }
我无法重定向到特定页面.当我想重定向用户时,我通常使用FacesContext中的NavigationHandler,但在这种情况下,没有FacesContext(FacesContext.getCurrentInstance()返回null).
根据这个post,HttpListener不能重定向用户,因为它不是请求的一部分.
题
解决方法
只要客户端没有发送HTTP请求,您就不能发送HTTP响应.就那么简单.这就是HTTP的工作原理.否则,如果任何网站能够在没有客户端请求的情况下无阻碍地推送HTTP响应,互联网将看起来非常不同.
基于JavaScript的心跳基于客户端的键盘/鼠标活动,如回答here,或像刷新页面一样,如答案here将是解决方案,如果您基本上是单页webapp(因此,您实际上没有使用会话范围,但视图范围),但如果您在同一会话中的多个选项卡/窗口中打开该页面,则不会很好地工作.
理论上,Websockets是向客户端推送某些东西的正确解决方案,但这又需要一个活动的会话.鸡蛋问题.而且,目前在使用中相对较广泛的旧版浏览器中也不行,所以现在应该仅用于渐进式增强.
最好的办法是定义一个错误页面,该页面在会话过期时终端用户调用一个操作的情况.参见javax.faces.application.ViewExpiredException: View could not be restored.