3

根据BalusC 的回答,我用

FacesContext.getCurrentInstance().getExternalContext().redirect(url);

在我的@PostConstruct方法中阻止 JSF 呈现视图并重定向用户。但是,当我尝试运行代码时,我仍然遇到java.lang.IllegalStateException了上面一行的异常。

WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.IllegalStateException
    at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:524)
    at StudentManagedBean.CourseSummary.init(CourseSummary.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

更新:我在我的@PostConstruct方法中添加了以下行:

System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());

我看到的是INIT true@PostConstruct我想知道在调用方法之前是否应该提交响应?

如果您能给我一个建议,我将不胜感激。

4

2 回答 2

3

正如我在更新中提到的,打印了以下行INIT true

System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());

我终于找到了为什么会出现上述情况。在我的页面上,在ManagedBean X包含重定向功能的被 引用之前UIComponent A,另一个被放置在页面结构上方的ManagedBean Y预先引用。结果,响应由 部分提交,这使得无法发送请求。UIComponent BUIComponent AManagedBean YManagedBean Xredirect

于 2013-03-30T06:29:52.530 回答
2

重定向在这里不起作用,因为即使响应已经完成并最终确定,JSF 也不够聪明,无法避免其运行生命周期事件的典型例程。

相反,您可以尝试从 RequestDispatcher 执行转发。转发与重定向在以下方面不同:

  • 由 servlet 在内部执行
  • 浏览器无动于衷
  • 原始网址保持不变

这是一些代码,显示了如何做到这一点......

RequestDispatcher dispatcher =
    ((ServletRequest) context.getExternalContext().getRequest())
    .getRequestDispatcher("/j_spring_security_logout");

try {
  dispatcher.forward((ServletRequest) context.getExternalContext().getRequest(),
  (ServletResponse) context.getExternalContext().getResponse());
} catch (ServletException e) {
  log.error("ServletException", e);
} catch (IOException e) {
  log.error("IOException", e);
}

通过这样做,您将过早地结束 FacesServlet 的执行并将其完全转发到不同的 servlet。我想从这个其他 servlet 可能会重定向到所需的位置。

于 2012-07-25T11:21:05.780 回答