我正在开发一个JSF Web应用程序,如果视图过期,我需要在其中显示“Session Expired”页面,但是所有其他页面都会出现一般技术错误页面。当我触发异常时,应用程序仅进入技术错误页面。这是错误页面定义:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/jsps/utility/sessionExpired.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/jsps/utility/technicalError.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/jsps/utility/technicalError.jsp</location>
</error-page>
我删除了technicalError.jsp错误页面元素并且它工作正常,但是当我把它们放回去时我无法访问sessionExpired.jsp页面。如何告诉Web容器评估这些标记的顺序,以便出现正确的页面?感谢。
答案 0 :(得分:16)
这是因为根据JSF规范,ViewExpiredException
被包装在ServletException
中。以下是JSF 1.2 specification的第10.2.6.2节的摘录:
10.2.6.2 FacesServlet
调用已保存的
execute()
实例的Lifecycle
方法,并传递 此请求的FacesContext
实例作为参数。如果是execute()
方法 抛出FacesException
,将其重新抛出ServletException
FacesException
为根本原因。
如何分配错误页面在Servlet API规范中指定。以下是Servlet API specification 2.5第9.9.2节的摘录:
SRV.9.9.2错误页面
如果包含
error-page
的没有exception-type
声明适合使用 类层次结构匹配,抛出的异常是ServletException
或 其子类,容器提取包装的异常,如下所定义ServletException.getRootCause
方法。 对错误进行了第二次传递 页面声明,再次尝试匹配错误页面 声明,但改为使用包装的异常。
在类层次结构中,ServletException
已匹配Throwable
,因此第二遍不会提取其根本原因。
要证明此指定行为,请将javax.faces.application.ViewExpiredException
替换为javax.servlet.ServletException
作为<exception-type>
并重试。您将看到正在显示的预期错误页面。
要解决此问题,只需删除 java.lang.Throwable
或java.lang.Exception
上的错误页面即可。如果没有一个异常特定错误页面匹配,那么无论如何它将回退到500
的错误代码。所以,你需要的只是:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/jsps/utility/sessionExpired.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/jsps/utility/technicalError.jsp</location>
</error-page>
更新:根据OP的(删除的)注释:为了可靠地测试它,你不能在bean构造函数或方法中执行throw new ViewExpiredException()
。它反过来会包含在一些EL异常中。您最终可以在rootCause
中添加打印Filter
的调试行以自行查看。
如果您正在使用Eclipse / Tomcat,则可以通过以下方式快速测试ViewExpiredException
:
答案 1 :(得分:0)
如BylusC所述,部署描述符不得包含任何会捕获ViewExpiredException(包裹在ServletException中)的错误页面处理程序,而不是正确的错误页面处理程序-ViewExpiredException的错误页面。
不要忘记验证服务器的部署描述符(例如TomEE / conf / web.xml)是否不包含java.lang.Throwable或java.lang.Exception错误页面定义。因为这两个web.xml基本上是合并的。
是-应用程序的web.xml优先于服务器的web.xml,但是如果应用程序的web.xml包含
和服务器的web.xml用于
然后,应用程序上下文将包含这两个的合并:
和ViewExpiredExcpetion错误处理将无法正常工作。