34

What is difference between a navigation in JSF

FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().getNavigationHandler().handleNavigation(context, null, url);

and a redirect

HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.sendRedirect(url);

and how to decide when to use what?

The issue with navigation is that page URL does not change unless faces-redirect=true is added to the query string of the navigation URL. However, in my case appending faces-redirect=true throws error if I want to redirect to a non-JSF page like a plain HTML page.

And another option is as BalusC suggested at JSF 2.0 redirect error

4

1 回答 1

83

首先,术语“重定向”在 Web 开发世界中是指向客户端发送一个空的 HTTP 响应,其中只有一个Location标头,其中包含客户端必须发送全新 GET 请求的新 URL。所以基本上:

  • 客户端向somepage.xhtml.
  • 服务器发回带有Location: newpage.xhtml标头的 HTTP 响应
  • 客户端发送一个 HTTP 请求newpage.xhtml(这会反映在浏览器地址栏中!)
  • 服务器发回 HTTP 响应,内容为newpage.xhtml.

您可以使用网络浏览器的内置/插件开发工具集对其进行跟踪。在 Chrome/IE9/Firebug 中按 F12 并检查“网络”部分以查看它。

JSF 导航处理程序不发送重定向。相反,它使用目标页面的内容作为 HTTP 响应。

  • 客户端向somepage.xhtml.
  • 服务器发回 HTTP 响应,内容为newpage.xhtml.

但是由于原始 HTTP 请求是 to somepage.xhtml,所以浏览器地址栏中的 URL 保持不变。如果您熟悉基本的 Servlet API,那么您应该明白这与RequestDispatcher#forward().


HttpServletResponse至于从 JSF 引擎盖下拉出并调用sendRedirect()它是否正确使用;不,这不是正确的用法。你的服务器日志会被IllegalStateExceptions 弄得乱七八糟,因为这样你就不会告诉 JSF 你已经接管了响应处理的控制权,因此 JSF 不应该做它的默认响应处理工作。您实际上应该在FacesContext#responseComplete()之后执行。

此外,每当您需要从javax.servlet.*JSF 工件(如托管 bean)中的包中导入某些内容时,您绝对应该停止编写代码并三思而后行,如果您真的以正确的方式做事,并问自己是否还没有“标准 JSF 方式”,无论您试图实现什么和/或该任务是否真的属于 JSF 托管 bean(即在某些情况下,一个简单的servlet 过滤器会是一个更好的地方)。

在 JSF 中执行重定向的正确方法是faces-redirect=true在操作结果中使用查询字符串:

public String submit() {
    // ...
    return "/newpage.xhtml?faces-redirect=true";
}

或者ExternalContext#redirect()当您不在诸如 ajax 或 prerender 侦听器方法之类的操作方法中时使用:

public void listener() throws IOException {
    // ...
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + "/newpage.xhtml");
}

(是的,你不需要try-catch在它周围加上a IOException,只要让异常通过throws,servletcontainer就会处理它)

或者NavigationHandler#handleNavigation(),如果您使用 XML 导航案例和/或带有一些内置侦听器的自定义导航处理程序,则在特定情况下使用:

public void listener() {
    // ...
    FacesContext fc = FacesContext.getCurrentInstance();
    NavigationHandler nh = fc.getApplication().getNavigationHandler();
    nh.handleNavigation(fc, null, "/newpage.xhtml?faces-redirect=true");
}

至于为什么导航处理程序对“纯 HTML”文件失败,这仅仅是因为导航处理程序只能处理 JSF 视图,不能处理其他文件。那时你应该使用ExternalContext#redirect()

也可以看看:

于 2012-06-30T20:36:21.183 回答