我已经通过谷歌和stackoverflow进行了搜索,但找不到任何类似的问题。
在我的项目中,我正在正确处理ViewExpiredException,并向用户显示当前会话已超时的自定义页面。这很好用,但我希望在此消息显示给用户之前做一些事情。实际上我在这里使用2个不同的会话,一个在前端,一个在后端,因此我们的想法是当前一个超时时不开始新的后端会话。 当我在doFilter方法中时,是否有可能获取ViewExpiredException,所以我不开始新的后端会话(仅仅因为它不需要)?或者还有其他方法吗?
我已经尝试通过
获取当前上下文FacesContext fc = FacesContext.getCurrentInstance();
但显然上下文为空,因为会话超时。 在ExceptionHandlerWrapper中,我可以访问UnhandledExceptionQueuedEvents,但这对我没有帮助,因为我之前需要这些信息。
我希望我的问题足够清楚。
提前感谢您的帮助!
此致 塞巴斯蒂安
答案 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之前运行。