我知道这里有很多关于这个问题的问题,但几乎所有问题都建议添加以下代码,因为 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 输出控制台屏幕截图。
发现问题
原来我的错误页面的 HTML 格式错误,它包含以下代码段,导致浏览器中出现不匹配的标签错误:
<script type="text/javascript">
//<![CDATA[
scrollTo(0, 0);
//]]>
</script>
这似乎过早地关闭了 CDATA 标记。这个 HTML 是<h:outputScript/>
标签的结果,我删除了它,因为我真的不需要它。