Redirect 重定向和导航/转发之间有什么区别?何时使用?

Redirect 重定向和导航/转发之间有什么区别?何时使用?,redirect,jsf-2,navigation,forward,Redirect,Jsf 2,Navigation,Forward,JSF中的导航有什么区别 FacesContext context = FacesContext.getCurrentInstance(); context.getApplication().getNavigationHandler().handleNavigation(context, null, url); 和重定向 HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().

JSF中的导航有什么区别

FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().getNavigationHandler().handleNavigation(context, null, url);
和重定向

HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.sendRedirect(url);
以及如何决定何时使用什么

导航的问题是页面URL不会更改,除非将
faces redirect=true
添加到导航URL的查询字符串中。然而,在我的例子中,如果我想重定向到非JSF页面(如普通HTML页面),则追加
faces redirect=true
会引发错误

另一种选择是,正如BalusC在

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

  • 客户端向
    somepage.xhtml
    发送HTTP请求
  • 服务器用
    位置:newpage.xhtml
    头返回HTTP响应
  • 客户端向
    newpage.xhtml
    发送HTTP请求(这会反映在浏览器地址栏中!)
  • 服务器返回一个HTTP响应,内容为
    newpage.xhtml
您可以使用webbrowser的内置/附加开发工具集跟踪它。按Chrome/IE9/Firebug中的F12键,查看“网络”部分

JSF navigationhandler不发送重定向。相反,它使用目标页面的内容作为HTTP响应

  • 客户端向
    somepage.xhtml
    发送HTTP请求
  • 服务器返回一个HTTP响应,内容为
    newpage.xhtml
但是,由于最初的HTTP请求是对
somepage.xhtml
,浏览器地址栏中的URL保持不变。如果您熟悉,那么您应该了解这与


从JSF引擎罩下拉出
HttpServletResponse
并在其上调用
sendRedirect()
是否正确使用;不,那不是正确的用法。您的服务器日志将被
IllegalStateException
s弄得乱七八糟,因为这样您就不会告诉JSF您已经接管了响应处理的控制权,因此JSF不应该执行其默认的响应处理工作。事实上,你应该在事后执行

此外,每当您需要从JSF工件(如托管bean)中的
javax.servlet.*
package导入某些内容时,您都应该完全停止编写代码,并仔细考虑是否确实以正确的方式进行了操作,并问问自己是否已经有了“标准JSF方式”对于您试图实现的任何目标和/或任务是否真正属于JSF管理的bean(也就是说,在某些情况下,简单应用程序可能是更好的地方)

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

public String submit() {
    // ...
    return "/newpage.xhtml?faces-redirect=true";
}
或者在不在操作方法(如ajax或prerender侦听器方法)内时使用:

public void listener() throws IOException {
    // ...
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + "/newpage.xhtml");
}
(是的,您不需要在
IOException
上的周围放置
try catch
,只要让异常通过
throws
,servletcontainer就会处理它)

或者在特定情况下使用,如果您使用的是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()

另见:

感谢巴鲁的详细解释。我是JSF新手,这有助于我理解其中的细微差别。也参考了您在链接上的评论-添加空字符串确实会将我返回到起始页,但也会显示错误消息作为找到的无效处理程序。我不能在这里使用faces redirect=true,因为我想返回一些消息到起始页。有指针吗?如果重定向在同一路径上,那么您可以使用
Flash#setKeepMessages()
将所有
FacesMessage
s保留在Flash范围内。谢谢BalusC,您刚刚让我免于被Ajax自杀。几个月来,我一直在为两个不同的项目与联合国作出反应。当JSF启动新页面时,它们的所有事件都被预先使用,除非随机选择的命令按钮使ajax=“false”大量分散。在重新阅读了您对这篇文章的回复后,我突然想到尝试使用re direct清除JSF中的表单工作区。它在页面和支持bean操作中都发挥了绝对的作用。缺点是我现在必须重新访问我的所有代码。我认为这里有一个输入错误:“客户端向somepage.xhtml发送一个HTTP请求。服务器用newpage.xhtml的内容发送一个HTTP响应。”您向“somepage.xhtml”发送了请求,但得到了“newpage.xhtml”的内容,对吗?或者我遗漏了什么=?@Muntaser:不,没有输入错误。语句“您向”somepage.xhtml“发送了请求,但得到了”newpage.xhtml“的内容是正确的。如果您仍然不理解它,请后退一步,在深入研究JSF之前先学习基本的servlet。