1

我知道这里有很多关于这个问题的问题,但几乎所有问题都建议添加以下代码,因为 FullAjaxExceptionHandler “上方”还有另一层发送普通重定向而不是执行 Ajax 重定向(参见这个类似的问题) :

if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
// JSF ajax request. Return special XML response which instructs JavaScript that it should in turn perform a redirect.
response.setContentType("text/xml");
response.getWriter()
    .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
    .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", loginURL);
} else {
    // Normal request. Perform redirect as usual.
    response.sendRedirect(loginURL);
}

我的问题是我只是配置 Omnifaces 的 FullAjaxExceptionHandler 来完成所有错误处理,我没有 Spring Security 或容器管理的安全性在 FullAjaxExceptionHandler 可以做之前拦截请求。我可以断点到 FullAjaxExceptionHandler 并看到当执行以下代码行时,我的错误页面仍然没有被重定向。

String viewId = Faces.normalizeViewId(errorPageLocation);
ViewHandler viewHandler = context.getApplication().getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(context, viewId);
context.setViewRoot(viewRoot);
context.getPartialViewContext().setRenderAll(true);
        ...
    context.renderResponse();

相反,异常起源的 Ajax 请求在其响应正文中包含以下内容:

<?xml version='1.0' encoding='UTF-8'?>
    <partial-response>
        <changes>
            <update id="javax.faces.ViewRoot"><![CDATA[<html xmlns="http://www.w3.org/1999/xhtml">... html of error page here ... </html>]]></update>
            <update id="javax.faces.ViewState"><![CDATA[-3527653129719750158:5595502883804776498]]></update>
        </changes>
    </partial-response>

看起来 FullAjaxExceptionHandler 没有做它应该做的事情,或者我错过了什么?

更新

附加浏览器 JS 输出控制台屏幕截图。JS输出控制台

发现问题

原来我的错误页面的 HTML 格式错误,它包含以下代码段,导致浏览器中出现不匹配的标签错误:

<script type="text/javascript">
//<![CDATA[
scrollTo(0, 0);
//]]>
</script>

这似乎过早地关闭了 CDATA 标记。这个 HTML 是<h:outputScript/>标签的结果,我删除了它,因为我真的不需要它。

4

2 回答 2

2

在最初的问题之后多年,现在使用 Wildfly 15、JSF 2.3、OmniFaces 3.2,我偶然发现了一个类似的问题:在 ajax 调用期间出现异常时 FullAjaxExceptionHandler 的部分响应格式错误。原因是响应中的嵌套 CDATA,因此注释掉了响应的一部分,导致 XML 解析错误。罪魁祸首似乎是 JSF 标记 ui:debug。我已删除该声明,现在它按预期工作。

于 2019-01-11T11:04:00.063 回答
1

ajax 响应看起来非常好,它<update id="javax.faces.ViewRoot">包含整个错误页面文档,所以FullAjaxExceptionHandler它的工作正常。

在检索到 ajax 响应之后,您的具体问题更有可能在客户端甚至错误页面文档本身中引起。然后轮到 JavaScript 解析该 ajax 响应并相应地替换当前的 HTML 文档。检查浏览器的 JavaScript 控制台应该可以提供有关该步骤中问题的任何线索。在您的特定情况下,问题似乎是由CDATA渲染内容周围的嵌套块引起的,而嵌套块<h:outputScript>又导致 JavaScript 解析错误。

不幸的是,我手头的任何 Mojarra 版本都无法重现该问题。也许您在某个地方有一个负责添加该CDATA块的自定义/第 3 方脚本渲染器。该脚本渲染器应在返回时跳过该CDATA块。如果您仍然无法弄清楚,那么最好的办法是用纯 HTML替换它,甚至完全删除它——就像您最终所做的那样。PartialViewContext#isAjaxRequest()true<h:outputScript><script>

于 2013-09-03T20:41:40.220 回答