h:body 使用 FullAjaxExceptionHandler 时未重新呈现

h:body not rerendered when using FullAjaxExceptionHandler

我正在使用 OmniFaces FullAjaxExceptionHandler 来显示错误页面。错误页面显示正确,但我对这些页面的样式有疑问。

我的应用程序使用的模板在 body 元素上定义了 CSS 类。这些 类 对于正常页面和错误页面是不同的:

普通页面:

<h:body styleClass="main-body layout-compact">

错误页面:

<h:body styleClass="exception-body error-page">

当FullAjaxExceptionHandler处理异常时,会执行一个到错误页面的转发(基于web.xml中的<error-page>机制)。显然这不会重新呈现 <h:body> 标签,因为在检查 HTML 输出时,我可以看到 <body> 标签仍​​然包含来自 CSS 类正常页面(而不是错误页面的类)。

好像是把原来<h:body>的内容替换成了错误页面<h:body>的内容,而不是只替换完整的<h:body>。我不知道这是否是默认的 JSF / FullAjaxExceptionHandler 行为。

有什么方法可以让 <h:body> 呈现正确的 CSS 类?将 CSS 类 从 <h:body> 移开不是一个选项。

不幸的是"by design"。 JSF 在执行 ajax 导航时不会替换整个文档,但它只会替换单个 <head><body> 元素的子元素,而不会影响父元素。这样做是出于历史原因;较旧的 Internet Explorer 版本不支持完全替换它们。

我自己所做的就是简单地将样式放入 <main> 元素中。 <header><footer> 在最终的 HTML 输出中通常是相同的。基本上:

<html>
    <head>
        <title>...</title>
    </head>
    <body>
        <header>...</header>
        <main class="#{page.type}">...</main>
        <footer>...</footer>
    </body>
</html>

如果您确实需要修改 <body class>,那么最好的办法是通过嵌入在错误页面模板中的 JavaScript 来完成。

<h:outputScript rendered="#{faces.ajaxRequest}">
    document.body.className = "exception-body error-page";
</h:outputScript>

注意:#{faces} 仅在 OmniFaces 2.5 之后可用,如果您使用的是旧版本,请改用 #{facesContext.partialViewContext.ajaxRequest}).