我知道这个问题上有很多问题,但几乎所有问题都建议添加以下代码,因为FullAjaxExceptionHandler上面还有另一层发送普通重定向而不是进行Ajax重定向(参见{ {3}}):
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输出控制台屏幕上限。
问题已识别
原来我的错误页面的HTML格式不正确,它包含以下代码段,导致浏览器中的标记错误不匹配:
<script type="text/javascript">
//<![CDATA[
scrollTo(0, 0);
//]]>
</script>
这似乎过早地关闭了CDATA标签。这个HTML是<h:outputScript/>
标记的结果,我删除了它,因为我不需要它。
答案 0 :(得分:1)
ajax响应看起来完全正常,它包含整个错误页面文档的<update id="javax.faces.ViewRoot">
,因此FullAjaxExceptionHandler
正确地完成了它的工作。
在检索到ajax响应之后,更有可能在客户端或甚至在错误页面文档中导致您的具体问题。然后,JavaScript轮流解析ajax响应并相应地替换当前的HTML文档。检查浏览器的JavaScript控制台应该提供有关该步骤中问题的任何线索。在您的特定情况下,问题似乎是由CDATA
呈现的内容周围的嵌套<h:outputScript>
块引起的,这反过来导致JavaScript解析错误。
不幸的是,我无法用我手头的任何Mojarra版本重现这个问题。也许你的某个地方是自定义/第三方脚本渲染器,负责添加CDATA
块。 CDATA
返回PartialViewContext#isAjaxRequest()
时,该脚本渲染器应跳过true
块。如果您仍然无法弄明白,那么最好的办法是用普通的HTML <h:outputScript>
替换<script>
,或者甚至完全删除它 - 就像你最终做的那样。
答案 1 :(得分:1)
最初提出问题的很多年后,现在使用Wildfly 15,JSF 2.3,OmniFaces 3.2,我偶然发现了一个类似的问题:FullAjaxExceptionHandler的部分响应格式错误,以防ajax调用期间发生异常。原因是响应中嵌套了CDATA,从而注释掉了响应的一部分,从而导致XML解析错误。罪魁祸首似乎是JSF标签ui:debug。我删除了该声明,现在它可以按预期运行。