【问题标题】:ViewExpiredException shown in java.lang.Throwable error-page in web.xmlWeb.xml 中的 java.lang.Throwable 错误页面中显示的 ViewExpiredException
【发布时间】:2011-03-13 12:35:10
【问题描述】:

我正在开发一个 JSF Web 应用程序,如果视图过期,我需要在其中显示“会话过期”页面,但对于所有其他人来说,我需要显示一般技术错误页面。当我触发异常时,应用程序只会进入技术错误页面。这是错误页面定义:

<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 容器评估这些标签的顺序,以便出现正确的页面?谢谢。

【问题讨论】:

    标签: jsf servlets web.xml custom-error-pages viewexpiredexception


    【解决方案1】:

    这是因为根据 JSF 规范,ViewExpiredException 被包装在 ServletException 中。这是JSF 1.2 specification第10.2.6.2章的摘录:

    10.2.6.2 FacesServlet

    调用保存的Lifecycle实例的execute()方法,传递 FacesContext 此请求的实例作为参数。如果execute() 方法 抛出 FacesException将其重新作为 ServletException 抛出 FacesException 是根本原因

    如何分配错误页面在 Servlet API 规范中指定。这是Servlet API specification 2.5第9.9.2章的摘录:

    SRV.9.9.2 错误页面

    如果 no 包含 exception-typeerror-page 声明适合使用 类层次匹配,抛出的异常是ServletException 或 其子类,容器提取包装的异常,如定义 ServletException.getRootCause 方法。 第二次通过 克服错误 页面声明,再次尝试匹配错误页面 声明,但使用包装的异常。

    在类层次结构中,ServletException 已经与 Throwable 匹配,因此不会为第二遍提取其根本原因。

    要证明此指定行为,请将 javax.faces.application.ViewExpiredException 替换为 javax.servlet.ServletException&lt;exception-type&gt; 并重试。您将看到正在显示的预期错误页面。

    要解决此问题,只需删除java.lang.Throwablejava.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 异常中。您最终可以在Filter 中添加一个打印rootCause 的调试行以自己查看。

    如果您使用的是 Eclipse/Tomcat,测试ViewExpiredException 的快速方法如下:

    1. 使用简单的命令按钮创建一个 JSF 页面,部署并运行它并在 webbrowser 中打开它。
    2. 回到 Eclipse,右键单击 Tomcat 服务器并选择 Clean Tomcat Work Directory。这将重新启动 Tomcat丢弃所有序列化会话(重要!仅重新启动 Tomcat 是不够的)。
    3. 返回网络浏览器并按下命令按钮(无需事先重新加载页面!)。

    【讨论】:

    • 感谢您的详细解释。不幸的是,该解决方案不起作用。出现技术错误页面而不是会话过期页面。我通过在会话中间重新启动应用程序来终止会话。我发现我可以在该 try 块中执行 response.sendRedirect 而不是引发运行时异常,但是我正在硬编码视图的路径而不是让容器控制它。不是首选,但我不知道还能做什么。
    • 这在 Tomcat 6.0.20 上运行良好。您使用的是什么 servlet 容器?你得到了什么根本原因?
    • 我没有提到我无法删除错误代码 500 的 块。它是我商店编码标准的一部分。
    • Websphere 应用服务器 v6.1.
    • @PavelS:哦,这样。只需删除 java.lang.Throwable/java.lang.Exception 并保留 500 作为其他异常的一般后备。另请参阅答案。
    【解决方案2】:

    正如 BylusC 所提到的,部署描述符不能包含任何会捕获 ViewExpiredException(包装在 ServletException 中)的错误页面处理程序,而不是正确的 - ViewExpiredException 的错误页面。

    不要忘记验证服务器的部署描述符(例如 TomEE/conf/web.xml)不包含 java.lang.Throwable 或 java.lang.Exception 错误页面定义。因为这两个web.xml基本上是合并的。

    是 - 应用程序的 web.xml 优先于服务器的 web.xml,但如果应用程序的 web.xml 包含

    • 错误页面 500 (/error.xhtml)

    和服务器的 web.xml

    • 500 (/500.html) 和用于
    • 可抛出的 (/bigerror.html)

    那么应用上下文将包含这两者的合并:

    • 500 (/error.xhtml)
    • 可抛出的 (/bigerror.html)

    ViewExpiredExcpetion 错误处理将无法正常工作。

    【讨论】:

      猜你喜欢
      • 2014-03-15
      • 2013-02-25
      • 1970-01-01
      • 2012-08-20
      • 2010-09-25
      • 2013-12-14
      • 1970-01-01
      • 1970-01-01
      • 2013-04-13
      相关资源
      最近更新 更多