web.xml中的java.lang.Throwable错误页面中显示的ViewExpiredException [英] ViewExpiredException shown in java.lang.Throwable error-page in web.xml
问题描述
我正在开发一个JSF Web应用程序,如果视图过期,我需要在其中打开会话过期"页面,但对于所有其他页面,则需要打开一个常规技术错误页面.当我触发异常时,应用程序仅进入技术错误页面.这是错误页面的定义:
I'm working on a JSF web application in which I need to bring up a "Session Expired" page if the view expires, but a general technical error page for all others. The application only goes to the technical error page when I trigger the exception. Here's the error-page definitions:
<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容器评估这些标签的顺序,以便显示正确的页面?谢谢.
I removed the technicalError.jsp error page elements and it worked fine, but when I put them back I can't get to the sessionExpired.jsp page. How do I tell the web container the order to evaluate these tags so that the right page comes up? Thanks.
推荐答案
这是因为 ServletException
.这是 JSF 1.2规范的第10.2.6.2章的摘录:
This is because the ViewExpiredException
is been wrapped in a ServletException
as per the JSF specification. Here's an extract of chapter 10.2.6.2 of the JSF 1.2 specification:
10.2.6.2 FacesServlet
调用已保存的
Lifecycle
实例的execute()
方法,并传递 此请求的FacesContext
实例作为参数.如果execute()
方法 抛出FacesException
,将其重新抛出为ServletException
FacesException
是根本原因.
10.2.6.2 FacesServlet
Call the
execute()
method of the savedLifecycle
instance, passing theFacesContext
instance for this request as a parameter. If theexecute()
method throws aFacesException
, re-throw it as aServletException
with theFacesException
as the root cause.
如何分配错误页面在Servlet API规范中指定.这是 Servlet API规范2.5 的第9.9.2章的摘录:
How the error pages are allocated is specified in Servlet API specification. Here's an extract of chapter 9.9.2 of Servlet API specification 2.5:
SRV.9.9.2错误页面
如果包含
exception-type
的否error-page
声明适合使用 类层次结构匹配,并且抛出的异常是ServletException
或 子类,容器提取包装的异常,如ServletException.getRootCause
方法.对错误进行了第二遍 页面声明,再次尝试与错误页面匹配 声明,但改用包装的异常.
SRV.9.9.2 Error Pages
If no
error-page
declaration containing anexception-type
fits using the class-hierarchy match, and the exception thrown is aServletException
or subclass thereof, the container extracts the wrapped exception, as defined by theServletException.getRootCause
method. A second pass is made over the error page declarations, again attempting the match against the error page declarations, but using the wrapped exception instead.
在类层次结构中,ServletException
已经与Throwable
匹配,因此第二遍将不会提取其根本原因.
In class hierarchy, ServletException
already matches Throwable
, so its root cause won't be extracted for the second pass.
要证明此指定的行为,请将javax.faces.application.ViewExpiredException
替换为<exception-type>
,然后重试.您会看到预期的错误页面正在显示.
To prove this specified behaviour, replace javax.faces.application.ViewExpiredException
by javax.servlet.ServletException
as <exception-type>
and retry. You'll see the expected error page being displayed.
要解决此问题,只需删除错误页面上的java.lang.Throwable
或java.lang.Exception
.如果没有一个特定于异常的错误页面匹配,则无论如何它都会退回到错误代码为500
的页面.所以,您只需要这样:
To solve this, simply remove the error page on java.lang.Throwable
or java.lang.Exception
. If no one exception specific error page matches, then it will fall back to the one for error code of 500
anyway. So, all you need is this:
<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异常中.您最终可以在Filter
中添加打印rootCause
的调试行以自己查看.
Update: as per the (deleted) comment of the OP: to reliably test this you cannot do a throw new ViewExpiredException()
in a bean constructor or method or so. It would in turn get wrapped in some EL exception. You can eventually add a debug line printing rootCause
in the Filter
to see it yourself.
如果您使用的是Eclipse/Tomcat,则可以使用以下快速测试ViewExpiredException
的方法:
If you're using Eclipse/Tomcat, a quick way to test ViewExpiredException
is the following:
- 使用一个简单的命令按钮创建一个JSF页面,部署并运行它,然后在webbrowser中打开它.
- 返回Eclipse,右键单击Tomcat服务器,然后选择"清洁Tomcat工作目录" .这将重新启动Tomcat ,并丢弃所有序列化的会话(重要!仅重新启动Tomcat是不够的).
- 返回Web浏览器并按命令按钮(事先没有重新加载页面!).
- Create a JSF page with a simple command button, deploy and run it and open it in webbrowser.
- Go back to Eclipse, rightclick Tomcat server and choose Clean Tomcat Work Directory. This will restart Tomcat and trash all serialized sessions (important! just restarting Tomcat is not enough).
- Go back to webbrowser and press the command button (without reloading page beforehand!).
这篇关于web.xml中的java.lang.Throwable错误页面中显示的ViewExpiredException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!