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

JSF中的导航有什么区别?

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

和重定向

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

以及如何决定何时使用什么?

导航问题是,除非将faces-redirect=true添加到导航URL的查询字符串,否则页面URL不会更改。 但是,在我的情况下,如果我想重定向到一个非JSF页面,如普通的HTML页面,appending faces-redirect=true会抛出错误。

另一个选项是BalusC在JSF 2.0重定向错误时提示的

首先,术语“重定向”在Web开发世界中是向客户端发送空HTTP响应的动作,其中仅具有Location头,其中客户端必须发送新的GET请求的新URL。 所以基本上:

  • 客户端发送一个HTTP请求到somepage.xhtml
  • 服务器使用Location: newpage.xhtml标题返回HTTP响应
  • 客户端发送一个HTTP请求到newpage.xhtml (这反映在浏览器的地址栏!)
  • 服务器发送一个HTTP响应,内容为newpage.xhtml

您可以使用网页浏览器的内置/附件开发者工具集进行跟踪。 在Chrome / IE9 / Firebug中按F12,然后选中“网络”部分查看。

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

  • 客户端发送一个HTTP请求到somepage.xhtml
  • 服务器发送一个HTTP响应,内容为newpage.xhtml

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


至于是否从JSF引擎中提取HttpServletResponse并在其上调用sendRedirect()是正确的用法; 不,这不是正确的用法。 您的服务器日志将因IllegalStateException混乱,因为这样您就不会告诉JSF您已经接管了响应处理的控制,因此JSF不应该执行其默认响应处理作业。 事后你应该执行FacesContext#responseComplete()

另外,无论何时,只要需要从JSF构件(如托管bean)中的javax.servlet.*包中导入某些东西,就应该停止编写代码,并且如果确实以正确的方式做事,对于你试图实现的任何东西,或者如果这个任务真的属于一个JSF管理的bean(也有一些简单的servlet过滤器将会是一个更好的地方),已经不是一个“标准的JSF方式”。

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

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

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

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

(是的,你不需要在IOException上放一个try-catch ,只要让异常通过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()然后。

也可以看看:

  • 如何在JSF中导航? 如何使URL反映当前页面(而不是以前的页面)
  • 什么时候应该使用h:outputLink而不是h:commandLink?