在调用ExceptionHandlerWrapper中的handle()方法之前处理ViewExpiredException

时间:2014-01-23 15:09:07

标签: jsf-2 servlet-filters viewexpiredexception facescontext

我已经通过谷歌和stackoverflow进行了搜索,但找不到任何类似的问题。

在我的项目中,我正在正确处理ViewExpiredException,并向用户显示当前会话已超时的自定义页面。这很好用,但我希望在此消息显示给用户之前做一些事情。实际上我在这里使用2个不同的会话,一个在前端,一个在后端,因此我们的想法是当前一个超时时不开始新的后端会话。 当我在doFilter方法中时,是否有可能获取ViewExpiredException,所以我不开始新的后端会话(仅仅因为它不需要)?或者还有其他方法吗?

我已经尝试通过

获取当前上下文
FacesContext fc = FacesContext.getCurrentInstance();

但显然上下文为空,因为会话超时。 在ExceptionHandlerWrapper中,我可以访问UnhandledExceptionQueuedEvents,但这对我没有帮助,因为我之前需要这些信息。

我希望我的问题足够清楚。

提前感谢您的帮助!

此致 塞巴斯蒂安

1 个答案:

答案 0 :(得分:1)

通常在会话超时时触发POST请求时抛出ViewExpiredException。所以,这应该在过滤器中执行:

boolean post = "POST".equals(request.getMethod());
boolean timedout = request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid();

if (post && timedout) {
    // JSF will guaranteed throw ViewExpiredException when state saving is set to server.
}

但这并未涵盖所有可能的情况。当会话未超时时,也会发生ViewExpiredException。例如,当客户端传递了无效的javax.faces.ViewState参数,或者已经从LRU映射中修剪了关联的视图时,默认情况下可以保存15个视图。但是在调用FilterChain#doFilter()之前,在servlet过滤器内部无法检测到这种情况。你真的需要在JSF上下文中。您可以在PhaseListener中执行后端会话创建作业。例如。在应用请求值阶段的前期阶段,保证只有在有虚拟视图时才会调用。

顺便说一下,过滤器中的FacesContext不是null,因为会话超时了,但是因为负责创建它的FacesServlet还没有在那时被调用了。你知道,过滤器在servlet之前运行。