4

是否可以从托管 bean 的构造函数导航到另一个页面/视图?如果发生任何异常,我想要此重定向。我尝试了很多方法:

试一试:

getFacesContext().responseComplete();
getFacesContext().getApplication().getNavigationHandler().handleNavigation(getFacesContext(), null, "gotoPartError");    
getFacesContext().renderResponse();

尝试2:

getServletResponse().sendRedirect("partError.jspx")

尝试3:

getFacesContext().responseComplete();    
getFacesContext().getExternalContext().redirect(getServletRequest().getContextPath() + "/pages/partError.jspx");

尝试4:

RequestDispatcher dispatcher = getServletRequest().getRequestDispatcher("partError.jspx");
dispatcher.forward(getServletRequest(), getServletResponse());

尝试5:

FacesContext context = getFacesContext();
UIViewRoot newPage = context.getApplication().getViewHandler().createView(context, "/partError.jspx");
context.setViewRoot(newPage);
context.renderResponse();

尝试6:

ControllerContext.getInstance().getCurrentViewPort().setViewId("partError");

尝试 7:

Exception Handler in adfc-config.xml

尝试 8:

Custom service handler defined in /.adf/META-INF/services/oracle.adf.view.rich.context.Exceptionhandler which extends oracle.adf.view.rich.context.Exceptionhandler

尝试9:

By extending JSF Life Cycle

他们都没有工作。对于我收到的所有案例

java.lang.IllegalStateException: Cannot forward after response has been committed

在 JSF 1.2 中真的不可能吗?由于我使用的是 ADF 11.1.1.6.0,它使用 JSF 1.2,所以上面的一些“尝试”包含 ADF Faces 方式。

无论如何,我需要 JSF 1.2 或 ADF Faces 来导航到错误页面。我获得成功的唯一方法是使用从后端执行的 javascript 在出现错误_self的情况下在窗口中打开错误页面,但我真的不喜欢它。

在这件事上的任何指示都会非常有帮助。

4

1 回答 1

5

如果了解问题的原因,则更容易解决问题。一个好的例外基本上已经说明了问题原因的一切。

仔细看:

java.lang.IllegalStateException:提交响应后无法转发

响应已提交。这是一个不归路。或许你没有理解响应已经提交是什么意思(这导致你也没有理解异常本身)。

默认情况下,HTTP 响应被写入缓冲区,该缓冲区每 ~2KB 刷新一次,具体取决于服务器配置。响应缓冲区的刷新导致写入的字节实际从服务器发送到客户端。一旦第一次发生这种情况,则认为响应已提交。这是一个不归路。服务器无法从客户端取回已经写入的字节,以防服务器实际上需要在之后更改响应。

如果您有一些可能需要更改响应的代码,那么您应该在提交响应之前调用它。

在您的特定情况下,托管 bean 显然是在生成 HTML 输出期间的 JSF 呈现响应阶段中间构造的。生成的 HTML 输出的一部分已经发送到客户端(因此,响应已提交)。您显然在 JSF 页面中相对较晚地引用了请求范围的 bean,或者响应缓冲区相对较小,或者 HTML<head>相对较大,导致在<body>开始之前就已经刷新,等等。

您确实需要在渲染响应阶段之前调用代码。在 JSF 1.2 中,您可以使用<f:view beforePhase>

例如

<f:view beforePhase="#{bean.navigate}">

public void navigate(PhaseEvent event) {
    if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
        // Do here your job which should run right before the RENDER_RESPONSE.
    }
}

然后你的 Try-1 和 Try-3 就可以工作了(但是你可以把它们responseComplete()renderResponse()线条放在一边,它们已经隐含地得到了照顾)。

Try-2 and Try-4 are poor. You should avoid having javax.servlet.* imports in your backing bean. Try-5 is clumsy. Try-6, Try-7 and Try-8 are beyond my scope. Try-9 is doable, but extremely clumsy.

于 2013-07-07T17:20:20.993 回答