sendRedirect和forward原理及区别总结

一、原理. 
1
 Forward 

 

 

 

该图的交互过程如下:

浏览器访问Servlet1。

Servlet1想让Servlet2对客户端的请求进行响应,于是调用forward()方法,将请求转发给Servlet2进行处理。

Servlet2对请求做出响应。

交互过程可以看出,调用forward()方法,对浏览器来说是透明的,浏览器并不知道为其服务的Servlet已经换成Servlet2了,它只知道发出了一个请求,获得了一个响应。显示的URL始终是原始请求的URL。

sendRedirect()方法和forward()方法还有一个区别,那就是sendRedirect()方法不但可以在位于同一主机上的不同Web应用程序之间进行重定向,而且可以将客户端重定向到其他服务器上的Web应用程序资源。

 


      
这种方式是在服务器端作的重定向。服务器往client发送数据的过程是这样的:服务器在向客户端发送数据之前,是先将数据输出到缓冲区,然后将缓冲区中数据发送给client端。什么时候将缓冲区里的数据发送给client端呢? 

1)当对来自clientrequest处理完,并把所有数据输出到缓冲区
 
2)当缓冲区满
 
3)在程序中调用缓冲区的输出方法out.flush()response.flushbuffer()web container才将缓冲区中的数据发送给client
 

      
这种重定向方式是利用服务器端的缓冲区机制,在把缓冲区的数据发送到客户端之前,原来的数据不发送,将执行转向重定向页面,发送重定向页面的数据,重定向调用页的数据将被清除。如果在<JSP:FORWORD>之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么这种重定向方式将不起作用,这一点应该特别注意。
 

public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException 

response.setContentType("text/html; charset=UTF-8"); 
ServletContext sc = getServletContext(); 
RequestDispatcher rd = null; 
rd = sc.getRequestDispatcher("/index.jsp"); 
rd.forward(request, response); 


2
 sendRedirect 

 

 

 

交互过程可以看出,调用sendRedirect()方法,实际上是告诉浏览器Servlet2所在的位置,让浏览器重新访问Servlet2。调用sendRedirect()方法,会在响应中设置Location响应报头。要注意的是,这个过程对于用户来说是透明的,浏览器会自动完成新的访问。浏览器的地址栏中,可以看到,显示的URL是重定向之后的URL

该图的交互过程如下:

浏览器访问Servlet1。

Servlet1想让Servlet2为客户端服务。

Servlet1调用sendRedirect()方法,将客户端的请求重定向到Servlet2。

浏览器访问Servlet2。

Servlet2对客户端的请求做出响应。

 


      

这种方式是在客户端作的重定向处理。该方法通过修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,让浏览器对在location中指定的URL提出请求,使浏览器显示重定向网页的内容。该方法可以接受绝对的或相对的URLs。如果传递到该方法的参数是一个相对的URL,那么Web container在将它发送到客户端前会把它转换成一个绝对的URL 

public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException 

response.setContentType("text/html; charset=UTF-8"); 
response.sendRedirect("/index.jsp"); 
}

 

二、区别

 

1.response.sendRedirect(url)

1)重定向,不转发请求,地址栏的url已改变

2)request.getAttribute(""),request.getParamter("")都获取不了 

response.sendRedirect("/studyProject/myforward/end2.jsp?name=tomzhang");//可以带参数的

   例子

   end2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'end.jsp' starting page</title>
 <meta http-equiv="pragma" content="no-cache">
 <meta http-equiv="cache-control" content="no-cache">
 <meta http-equiv="expires" content="0">    
 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 <meta http-equiv="description" content="This is my page">
 <!--
 <link rel="stylesheet" type="text/css" href="styles.css">
 -->
  </head>
  <body>
   name:${param.name}, sex:${requestScope.sex}, the end page!
  </body>
</html>

 

 

 

 first2.jsp

 <%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'first.jsp' starting page</title>
 <meta http-equiv="pragma" content="no-cache">
 <meta http-equiv="cache-control" content="no-cache">
 <meta http-equiv="expires" content="0">    
 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 <meta http-equiv="description" content="This is my page">
 <!--
 <link rel="stylesheet" type="text/css" href="styles.css">
 -->
  </head>
  <body>
    This is my JSP page. <br>
    <%
    request.setAttribute("sex", "man");
    response.sendRedirect("/studyProject/myforward/end2.jsp");//绝对路径
    %>
  </body>
</html>

 

 

 

 

结果:
name:, sex:, the end page!
url变成
http://localhost:8080/studyProject/myforward/end2.jsp

 


2.<jsp:forward page="" />

1)请求转发,地址栏的url不变

2)可以传递额外的参数

<jsp:param name="" value=""/>

3)request.getAttribute("");//基于请求的request共享

request.getParamter("");//请求转发

4)等同requestDispatcher.forward(url); 

<jsp:forward page="/myforward/end.jsp?age=man">//可以带参数

*使用forward一定要注意url页面的链接,不要使用相对路径;url页面的当前路径其实是第1次请求时的当前路径,所以url页面的链接都应该采用绝对路径!

例子:
first.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'first.jsp' starting page</title>
 <meta http-equiv="pragma" content="no-cache">
 <meta http-equiv="cache-control" content="no-cache">
 <meta http-equiv="expires" content="0">    
 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 <meta http-equiv="description" content="This is my page">
 <!--
 <link rel="stylesheet" type="text/css" href="styles.css">
 -->
  </head>
  <body>
    This is my JSP page. <br>
    <%
    request.setAttribute("sex", "man");
    %>
    <jsp:forward page="/myforward/end.jsp">
      <jsp:param value="tomzhang" name="name"/>
    </jsp:forward>
  </body>
</html>

 

 

 

end.jsp

 

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'end.jsp' starting page</title>
 <meta http-equiv="pragma" content="no-cache">
 <meta http-equiv="cache-control" content="no-cache">
 <meta http-equiv="expires" content="0">    
 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 <meta http-equiv="description" content="This is my page">
 <!--
 <link rel="stylesheet" type="text/css" href="styles.css">
 -->
  </head>
  <body>
   name:${param.name}, sex:${requestScope.sex}, the end page!
  </body>
</html>

 

 结果:
name:tomzhang, sex:man, the end page!
url一直保持不变
http://localhost:8080/studyProject/myforward/first.jsp

 

 

 

三、详解

 1. 跳转方式
http://localhost:8080/Test应用
运用forward方法只能重定向到同一个Web应用程序中的一个资源。而sendRedirect方法可以让你重定向到任何URL。
表单form的action= "/uu ";sendRedirect( "/uu ");表示相对于服务器根路径。如
http://localhost:8080/Test应用(则提交至http://localhost:8080/uu);
Forward代码中的 "/uu "则代表相对与WEB应用的路径。如
http://localhost:8080/Test应用(则提交至http://localhost:8080/Test/uu);
2. (运用RequestDispatcher接口的Forward)方法
forward()无法重定向至有frame的jsp文件,可以重定向至有frame的html文件,
同时forward()无法在后面带参数传递,比如servlet?name=frank,这样不行,可以程序内通过response.setAttribute( "name ",name)来传至下一个页面.
重定向后浏览器地址栏URL不变. 

只有在客户端没有输出时才可以调用forward方法。如果当前页面的缓冲区(buffer)不是空的,那么你在调用forward方法前必须先清空缓冲区。
"/ "代表相对与web应用路径 

RequestDispatcher   rd   =   request.getRequestDispatcher( "/ooo ");
rd.forward(request,   response);提交至
http://localhost:8080/Test/ooo 

RequestDispatcher   rd   =   getServletContext().getRequestDispatcher( "/ooo ");
rd.forward(request,   response);提交至
http://localhost:8080/Test/ooo 

RequestDispatcher   rd   =getServletContext().getNamedDispatcher( "TestServlet ");(TestServlet为一个 <servlet-name> )
rd.forward(request,   response);提交至名为TestServlet的servlet 

如果在 <jsp:forward> 之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将不起作用,这一点应该特别注意。
另外要注意:它不能改变浏览器地址,刷新的话会导致重复提交
http://localhost:8080/Test/gw/page.jsp中转发
<jsp:forward   page= "OtherPage.jsp "/> 在JSP页面被解析后转换成pageContext.forward( "OtherPage.jsp ");
"/OtherPage.jsp "提交到
http://localhost:8080/Test/OtherPage.jsp
"OtherPage.jsp "提交到
http://localhost:8080/Test/gw/OtherPage.jsp 


(运用HttpServletResponse接口的sendRedirect)方法302
是在用户的浏览器端工作,sendRedirect()可以带参数传递,比如servlet?name=frank传至下个页面,
同时它可以重定向至不同的主机上,sendRedirect()可以重定向有frame.的jsp文件.

假设转发代码包含于注册的servlet-url为/ggg/tt;jsp为/ggg/tt.jsp:
绝对路径:response.sendRedirect( "
http://www.brainysoftware.com ")发送至http://www.brainysoftware.com
根路径:response.sendRedirect( "/ooo ")发送至
http://localhost:8080/ooo
相对路径:response.sendRedirect( "ooo ")发送至
http://localhost:8080/Test/ggg/ooo,

sendRedirect等同于此方式
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
String   newLocn   =   "/newpath/jsa.jsp ";
response.setHeader( "Location ",newLocn);

 


(Meta   Refresh)方法200
这种方法是由HTML提供的,Meta本身就是HTML标签。使用方法是: <meta   http-equiv= "refresh "   content= "5;   url=http://www.dreamdu.com/ "   />
相应的java代码
String   content=stayTime+ ";URL= "+URL;
response.setHeader( "REFRESH ",content);
3. 使用response.sendRedirect()地址栏将改变
使用request.getRequestDispatcher().forward(request,response)地址栏中的信息保持不变
4. request.setAttribute存的东西

只用通过方法2跳转   才能在新页取出来
5. redirect   会首先发一个response给浏览器,   然后浏览器收到这个response后再发一个requeset给服务器,   然后服务器发新的response给浏览器.   这时页面收到的request是一个新从浏览器发来的.
forward   发生在服务器内部,   在浏览器完全不知情的情况下发给了浏览器另外一个页面的response.   这时页面收到的request不是从浏览器直接发来了,可能己经放了数据.
所以: request.setAttribute存的东西
        只用通过方法2跳转   才能在新页取出来
 

 

 

 

 

 

本文图片和部分段落来自网络

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值