重定向和导航/转发和何时使用什么有什么区别?
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?