页面转发和重定向的区别

发布时间:2012-09-19 14:22:24   来源:文档文库   
字号:
全解forward()和sendRedirect 昨天在servlet中搞些页面重定向的问题,在处理页面的path时遇到了一些恼人的问题,今天来深究一下: Javax.servlet.RequestDispatcher.forward(ServletRequest request, ServletResponse response) Javax.servlet.http.HttpServletResponse.sendRedirect(String location) forward 作用于服务器端,重定向后客户端浏览器地址栏的URL不变,无法通过get方式传递参数,不过可以通过HttpServletResponse. setAttribute(key, values)来做: JDK的DOC中的描述: Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. This method allows one servlet to do preliminary processing of a request and another resource to generate the response. forward should be called before the response has been committed to the client (before response body output has been flushed). If the response already has been committed, this method throws an IllegalStateException. Uncommitted output in the response buffer is automatically cleared before the forward. 这个方法允许一个servlet对一个请求作完处理后,并使用另一个资源作响应。 forward应该在向客户端发出响应之前被调用(response的输出流被刷新之前),如果已经向客户端发出了响应,这个方法将抛出一个“IllegalStateException”的异常。未发出响应response的输出缓冲区在调用forward会被自动的清空。 得到RequestDispatcher引用的方法: 1、 javax.servlet.ServletContext.getRequestDispatcher(String path) JDK的DOC中的描述: The pathname must begin with a "/" and is interpreted as relative to the current context root. Use getContext to obtain a RequestDispatcher for resources in foreign contexts. This method returns null if the ServletContext cannot return a RequestDispatcher. 用的最多,最容易理解的方法,path必须是以“/”开头,路径是相对于全局上下文路径,对应于web应用的根目录 2、javax.servlet.ServletRequest.getRequestDispatcher(String path) JDK的DOC中的描述: The pathname specified may be relative, although it cannot extend outside the current servlet context. If the path begins with a "/" it is interpreted as relative to the current context root. This method returns null if the servlet container cannot return a RequestDispatcher. 可以是相对地址,以当前资源的根目录,但不能超出当前资源根目录。 可以是以“/”开头的地址,当前root作为根目录环境。 2、 javax.servlet.ServletContext.getNamedDispatcher(String name) JDK的DOC中的描述: Servlets (and JSP pages also) may be given names via server administration or via a web application deployment descriptor. 得到名为name的资源。 Servlets(也可是JSP 页面)可能会有个给定的名字,该名字是服务器或者web应用的部署描述web.xml提供的。 sendRe direct 工作在客户端,重定向后客户端浏览器地址栏的URL变为新的资源URL,可以通过get方式传递参数。 JDK的DOC的描述: Sends a temporary redirect response to the client using the specified redirect location URL. This method can accept relative URLs; the servlet container must convert the relative URL to an absolute URL before sending the response to the client. If the location is relative without a leading '/' the container interprets it as relative to the current request URI. If the location is relative with a leading '/' the container interprets it as relative to the servlet container root. If the response has already been committed, this method throws an IllegalStateException. After using this method, the response should be considered to be committed and should not be written to. 这个方法可以接受相对的URL,在发送响应之前servlet容器会将其转化为绝对的URL。如果相对的URL不以“/”开头,容器将解释为是相对当前请求的路径URI,如果是以“/”开头,则解释为是相对于servlet容器的更目录环境。 注意:如果已经向客户端响应了请求,这个方法将抛出一个“IllegalStateException”的异常。调用了这个方法后,这个响应是否被提交或是否提交完毕。 sendRedirect比较简单,参数location就是代表重定向目标新资源。 localtion可以有以下几种情况: 可以是绝对地址,如:http://localhost:8080/servlet/a.jsp 可以是相对地址,相对于当前访问资源的根目录,如:a.jsp 可以是以“/”开头的地址,则认为是先对该web应用的根目录,如:/a.jsp JSP/Servlet的重定向技术综述 有关JSP/Servlet的重定向技术综述如下[补充] 1.RequestDispatcher.forward() 是在服务器端起作用,当使用forward()时,Servlet engine传递HTTP请求从当前的Servlet or JSP到另外一个Servlet,JSP 或普通HTML文件,也即你的form提交至a.jsp,在a.jsp用到了forward()重定向至b.jsp,此时form提交的所有信息在b.jsp都可以获得,参数自动传递. 但forward()无法重定向至有frame的jsp文件,可以重定向至有frame的html文件,同时forward()无法在后面带参数传递,比如servlet?name=frank,这样不行,可以程序内通过response.setAttribute("name",name)来传至下一个页面. 重定向后浏览器地址栏URL不变. 例:在servlet中进行重定向 public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { response.setContentType("text/html; charset=gb2312"); ServletContext sc = getServletContext(); RequestDispatcher rd = null; rd = sc.getRequestDispatcher("/index.jsp"); //定向的页面 rd.forward(request, response); } 通常在servlet中使用,不在jsp中使用。 2.response.sendRedirect() 是在用户的浏览器端工作,sendRedirect()可以带参数传递,比如serv let?name=frank传至下个页面,同时它可以重定向至不同的主机上,sendRedirect()可以重定向有frame.的jsp文件. 重定向后在浏览器地址栏上会出现重定向页面的URL 例:在servlet中重定向 public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { response.setContentType("text/html; charset=gb2312"); response.sendRedirect("/index.jsp"); } 由于response是jsp页面中的隐含对象,故在jsp页面中可以用response.sendRedirect()直接实现重定位。 注意: (1).使用response.sendRedirect时,前面不能有HTML输出。 这并不是绝对的,不能有HTML输出其实是指不能有HTML被送到了浏览器。事实上现在的server都有cache机制,一般在8K(我是说JSP SERVER),这就意味着,除非你关闭了cache,或者你使用了out.flush()强制刷新,那么在使用sendRedirect之前,有少量的HTML输出也是允许的。 (2).response.sendRedirect之后,应该紧跟一句return; 我们已经知道response.sendRedirect是通过浏览器来做转向的,所以只有在页面处理完成后,才会有实际的动作。既然你已经要做转向了,那么后的输出还有什么意义呢?而且有可能会因为后面的输出导致转向失败。 比较: (1).Request Dispatcher.forward()是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址; (2).response.sendRedirect()则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。 前者更加高效,在前者可以满足需要时,尽量使用RequestDispatcher.forward()方法. 注:在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用HttpServletResponse.sendRequest()方法。 3. 它的底层部分是由RequestDispatcher来实现的,因此它带有RequestDispatcher.forward()方法的印记。 如果在之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将不起作用,这一点应该特别注意。 另外要注意:它不能改变浏览器地址,刷新的话会导致重复提交 4.修改HTTP header的Location属性来重定向 通过设置直接修改地址栏来实现页面的重定向。 jsp文件代码如下: <% response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); String newLocn = "/newpath/jsa.jsp"; response.setHeader("Location",newLocn); %> 5.JSP中实现在某页面停留若干秒后,自动重定向到另一页面 在html文件中,下面的代码: 它的含义:在5分钟之后正在浏览的页面将会自动变为target.html这一页。代码中300为刷新的延迟时间,以秒为单位。targer.html为你想转向的目标页,若为本页则为自动刷新本页。 由上可知,可以通过setHeader来实现某 页面停留若干秒后,自动重定向到另一页面。 关键代码: String content=stayTime+";URL="+URL; response.setHeader("REFRESH",content); 如果总结得不够全面,请各位发表自己的意见或经验。 由于response是jsp页面中的隐含对象,故在jsp页面中可以用response.sendRedirect()直接实现重定位。 注意: (1).使用response.sendRedirect时,前面不能有HTML输出。 这并不是绝对的,不能有HTML输出其实是指不能有HTML被送到了浏览器。事实上现在的server都有cache机制,一般在8K(我是说JSP SERVER),这就意味着,除非你关闭了cache,或者你使用了out.flush()强制刷新,那么在使用sendRedirect之前,有少量的HTML输出也是允许的。 (2).response.sendRedirect之后,应该紧跟一句return; 我们已经知道response.sendRedirect是通过浏览器来做转向的,所以只有在页面处理完成后,才会有实际的动作。既然你已经要做转向了,那么后的输出还有什么意义呢?而且有可能会因为后面的输出导致转向失败。 http://www.matrix.org.cn/thread.shtml?topicId=21362&forumId=14 在servlet/JSP编程中,服务器端重定向可以通过下面两个方法来实现: 1,运用javax.servlet.RequestDispatcher接口的forward方法, 2,或者运用javax.servlet.http.HttpServletResponse接口的sendRedirect方法。 要运用RequestDispatcher接口的forward方法,首先要得到一个RequestDispatcher对象。servlet技术提供了三种方式来得到它: 1.通过运用javax.servlet.ServletContext接口的getRequestDispatcher方法,将一个包含路径的String传递给其它资源。该路径是相对于ServletContext的根路径的。 2.通过运用javax.servlet.ServletRequest接口的getRequestDispatcher方法,将一个包含路径的String传递到其它资源。该路径是相对于当前的HTTP请求的。 3.通过运用javax.servlet.ServletContext接口的getNamedDispatcher方法,传递一个包含其它资源名字的String。 但要注意,你只有在客户端没有输出时才可以调用forward方法。如果当前页面的缓冲区(buffer)不是空的,那么你在调用forward方法前必须先清空缓冲区。否则,会抛出一个IllegalStateException。forward方法也可以用来将请求发送到一个静态的页面。 在运用RequestDispatcher对象的forward方法来将一个控件从一个叫做ABCServlet的servlet传递到另一个叫做XYZServlet的servlet时,最简单的方法就是把ABCServlet和XYZServlet的类文件放在同一个目录中。通过这种方法,你就可以从URLhttp://domain/VirtualDir/servlet/ABCServlet来调用ABCServlet,从URLhttp://domain/VirtualDir/servlet/XYZServlet来调用XYZServlet了。然后运用forward方法就很简单了。你可以从ServletRequest接口运用getRequestDispatcher,传递第二个servlet的名字。在ABCServlet中,你可以写下面的代 码: RequestDispatcherrd= request.getRequestDispatcher("SecondServlet"); rd.forward(request,response); 你不需要在XYZServlet前放/符号。这种方法是最简单的,因为你根本不需要担心两个servlets的路径。 稍复杂的方法就是把下面这个String传递到ServletRequest的getRequestDispatcher:"/servlet/XYZServlet" 如果你必须调用一个从ServletContext的getRequestDispatcher得到的RequestDispatcher对象的forward方法,你需要将“/VirtualDir/servlet/XYZServlet”作为路径参数来传递,如下: RequestDispatcherrd= getServletContext().getRequestDispatcher( "/servlet/XYZServlet"); rd.forward(request,response); 在结果servlet中就转换成了下面的代码:pageContext.forward("OtherPage.jsp"); 运用HttpServletResponse接口的sendRedirect方法 该方法把一个命令发送到浏览器,让浏览器对在location中指定的URL提出请求。该方法可以接受绝对的或相对的URLs。如果传递到该方法的参数是一个相对的URL,那么Webcontainer在将它发送到客户端前会把它转换成一个绝对的URL。如果地址是相对的,没有一个’/’,那么Webcontainer就认为它是相对于当前的请求URI的。 你应该运用哪种技巧? [QUOTE]为了编写最有效的代码,你应该了解这两种重定向技巧的不同。forward方法是在Webcontainer内部工作的。sendRedirect方法需要到客户端的一个往返。所以forward方法比sendRedirect要快。但是,运用forward方法有局限性,你只能重定向到同一个Web应用程序中的一个资源。而sendRedirect方法可以让你重定向到任何URL。结论:如果可以解决你的问题,那么就用forward方法。只有当你不能用forward方法时才运用sendRedirect方法。 forward不会改变当前浏览器地址栏中的路径 14:10 | 固定链接 | 评论 (0) | 引用通告 (0) 固定链接 关闭 理解转发与重定向 不要仅仅为了把变量传到下一个页面而使用session作用域,那会无故增大变量的作用域,转发也许可以帮助你解决这个问题。 重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。 转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。 正文开始: 先是看上去不同,他们的调用分别如下: request.getRequestDispatcher("apage.jsp").forward(request, response);//转发到apage.jsp response.sendRedirect("apage.jsp");//重定向到apage.jsp 在jsp页面中你也会看到通过下面的方式实现转发: 我在初学jsp的时候,对这两个概念非常模糊,看别人的例子的时候,也是一头雾水,不知道什么时候该用哪个。希望下面的解说能对你有所帮 助。 提到转发和重定向就不得不提到request作用域。很多初学者都知 道当我们提交一个表单时,就创建了一个新的请求。实际上,当我们点击一个 链接时,也创建了一个新的请求。那么一个请求的作用于到底有多大呢?例如: 在页面a.jsp中有一个链接这是指向b的一个链接,而且还带了一个参数。当我们点击这个连接的时候,就产生了一 个请求,为了明确起见,我们把它叫做requestA->B。现在,在b.jsp页面中我们就可以从这个请求中获取信息了。在b.jsp中你可以写入out.pr intln(request.getParameter("id"))进行测试。下面更复杂一点,我们在b.jsp页面中增加下面的语句: request.setAttribute("name","funcreal"); out.println(request.getAttriblute("name"));//成功显示了name变量的值。 现在在b.jsp中再增加一个链接:这是指向c的一个链接,而且还带了一个参数,当我们点击这个连接的时候,将 产生一个新的请求,这时requestA-B也就安息了,新的请求叫做requestB-C。同样的道理,在c.jsp中,我们可以访问到的变量只有age,因为i d,name这两个变量都属于requestA-B,此时他已经不存在了。下面是源代码: a.jsp 指向b.jsp,而且还带了一个参数id=1。requestA-B现在诞生了 b.jsp requestA-B已经结束了。指向c.jsp,而且还带了一个参数age=23 c.jsp 那么转发又是怎么回事呢?现在增加一个页面叫做d.jsp,并且在c.jsp中前面增加一句 d.jsp requestB-C的魔爪已经伸到了d.jsp页面 运行程序,你会发现c页面中的内容没有显示出来,因为forward是自动执行的,地址栏中虽然是c.jsp但实际上,但浏览器中显示的已经是d.js p的内容了,而且看到了从b.jsp传过来的参数。你可以简单得这样理解:转发,就是延长了requestB-C的作用域, page="d.jsp"/>,这一句话实际上是把c.jsp和d.jsp粘到了一起,他们就像是在一个页面中。 如果你用过struts,那么你就知道为什么在Action中,最后一句几乎总是mapping.findForward("xxx");了。因为我们在这个Action中设置的请 求作用域的变量都将会在下一个页面(也许是另一个Action)中用到,所以要用转发。 总结: 用重定向和转发不是一个习惯问题。而是什么情况下必须用什么的问题。 不要仅仅为了把变量传到下一个页面而使用session作用域,那会无故增大变量的作用域,转发也许可以帮助你解决这个问题。 重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。 转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。

本文来源:https://www.2haoxitong.net/k/doc/2656001c6bd97f192279e962.html

《页面转发和重定向的区别.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式