web.xml中定义的错误页面嵌入在部分呈现的JSF页面中

jc1*_*c12 5 jsf-2

我在web.xml中定义了以下内容:

<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/shared/errors/DefaultErrorPage.xhtml</location>
</error-page>
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/shared/errors/ViewExpired.xhtml</location>
</error-page>
Run Code Online (Sandbox Code Playgroud)

我也在faces-config.xml中使用Omnifaces的FullAjaxExceptionHandler:

<factory>
    <exception-handler-factory>
        org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory
    </exception-handler-factory>
</factory>
Run Code Online (Sandbox Code Playgroud)

FullAjaxExceptionHandler对于ajax调用工作正常,但是当我直接点击页面并且出现错误时,它开始呈现我试图去的页面,但它没有完成,然后在web中定义了错误页面.呈现xml,这导致在部分呈现的页面之后嵌入错误页面.

(我正在使用具有Mojarra JSF 2.1.3的Glassfish 3.1.1)编辑:现在使用Glassfish 3.1.2.2和JSF 2.1.11

编辑:发现以下内容:发生错误的页面使用模板(<ui:composition template="/shared/shared/commonLayout.xhtml">)如果我更改它以使页面不再使用模板,然后只需添加模板中的所有代码,那么它可以正常工作.

Bal*_*usC 5

在抛出异常之前已经提交响应时会发生这种情况.当ServletOutputStream#flush()以某种方式明确调用JSF封面时,响应将被提交,这通常仅在响应缓冲区(大多数容器中通常默认为2KB)溢出时才会提交.坚定的回应是不归路.服务器无法从客户端返回已发送的字节.服务器基本上有两个选项:

  • 保持响应不变,并将异常仅记录到服务器日志中.
  • 尝试将错误页面写入响应.

您的Glassfish设置显然选择了第二种方式.它们都不是完美的.客户端仍然会得到一个半熟的HTML响应,无论它最终看起来像最终用户,取决于webbrowser如何在解释和呈现迄今为止获得的HTML方面做得最好.

但是,作为JSF开发人员,您可以使用多种方法来避免这种情况发生.首先,为什么呈现响应期间抛出异常?这不是实际上表明您自己的代码中的错误?呈现响应之前,您不能更好地执行异常敏感的业务作业吗?你可以使用其中<f:event type="preRenderView">的这个.

<f:event type="preRenderView" listener="#{bean.init}" />
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因这确实不是一个选项,您可以考虑将响应缓冲区大小增加到大于最大HTML响应的大小,以便在异常发生之前不会自动刷新响应.您可以通过以下上下文参数执行此操作,该参数假定每个HTML响应都符合100KB限制:

<context-param>
    <param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name>
    <param-value>102400</param-value><!-- 100KB -->
</context-param>
Run Code Online (Sandbox Code Playgroud)