讨论它们的区别之前,先让我们看下它们是怎样被调用的?
Response.sendRedirect(redirect)
redirect="AccessGoalCharts.jsp?rcatID=3&rhaID=All_&doSearch=true”
实际上,container会将这个 redirect的 url字符串重新送到
Browser interface,相当于用户重新在address栏中输入了一个地址,赫赫,
这样解释简单吧?
request.getRequestDispatcher("welcome.jsp").forward(request, response);
我们查一下web.xml,如果我们没有找到相应的servlet mapping,那么这套
Request和response(也就是原来的browse interface)就被转到 welcome.jsp
去处理了,welcome.jsp产生的html page也就被返回到了 response(也就是原来的browser interface).如果在web.xml当中我们找到了相应的 servlet mapping, 如下所示,
<servlet-mapping>
<servlet-name>DemoServlet</servlet-name>
<url-pattern>/welcome.jsp</url-pattern>
</servlet-mapping>
那么这套request和response就被forward到了DemoServlet的 doGet或者 doPost去处理了,问题是,getRequestDispatcher为什么不改名字叫做 getURLDispatcher,这不是更加符合 由 web.xml控制的实际情况吗?
Request.getRequestDispatcher(“welcome.jsp”).include(request,response)和 forward(request,response)的情况一模一样,区别在于,这个response,也就是 Browse Interface在接收了welcome.jsp产生的html page以后(假设在 web,xml当中没有相对应于 welcome.jsp的 servlet-mapping),还可以在这个response( browser interface)当中接收其他的html page,我测试过的代码如下所示:
request.getRequestDispatcher("welcome.jsp").include(request, response);
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is " + request.getParameter("name"));
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
好了,还有一些考试大全中经常描述的 forward对于 用户来讲是透明的,而 reDirect对于用户来讲是 在browser的地址栏中可见的讲法,都是正确的讲法.
好,我再用通俗的讲法讲解一下 sendRedirct, forward, include的区别 (基于 servlet api 2.2以上)
(1)response.sendRedirect(String location)
Sends a temporary redirect response to the client using the specified redirect location URL 实际上是给client返回一个临时的response,里面也就一个url,告诉client,我现在已经处理完了你的request, 你应该进入这个URL,它会处理你的request了(这个request的内容您这个client可能就不太清楚了) (2)requestDispatcher.forward(request, response)
现在的servlet把控制权完全交给另外一个Servlet,这个servlet已经预先处理过的request和response也一并移交过去, 这个forward的过程实际上Client并不知道,是Server端的几个servlet collaboration. (3)include又和 forward有什么区别呢?
赫赫, requestDispatcher.include(request, response) 好像没有什么区别啊,include仅仅是include, 接收request的那个servlet (called servlet),它往printerWriter(或OutputStream, writer是写文本 而stream是写二进制)中写的内容是 caller servlet往 printerWriter(或 outputStream)中写的内容的一部分.而 requestDispatcher.forward(request, response)就不一样了,calling servlet控制权完全交出去了, calling servlet 的response buffer中的东西都被清空了,所以如果你要 forward,就是转移控制权的话, 你根本就不应该在calling servlet 中的response里面写任何东西,写了的话一旦 forward的话也就白瞎了,因为被清空了嘛. (4)为什么 request.getRequestDispatcher 而 response.sendRedirect(new_url)呢?
我举个简单的例子, request.getRequestDispatcher("/servlets/bookItems?bookId=18871"); 赫赫,在 getRequestDispatcher的同时还可以往 request当中塞一个parameter啊. 而response.sendRirect(new_url)呢, 这个new_url可是会返回给client browser看的,所以 当然是response.sendRedirect(new_url)了. Servlet中forward和redirect的区别
forward方式:request.getRequestDispatcher("/somePage.jsp").forwardrequest, response); -------------------------------------------------------------------------------------------------- 在Java Web开发中,经常会用到跳转页面的方法,一般有下面两种方法。 -------------------------------------------------------------------------------------------------- 清空当前缓存: 在之前撰写JSP的例子中,实用了out这个对象,这个对象您不用事先宣告,就可以在JSP网页中使用,这是JSP所提供的隐含对象 (Implicit Object),在转译为Servlet之后,out会转换为对应于javax.servlet.jsp.JspWriter型态的对象。 JspWriter直接继承自java.io.Writer,您可以使用println()、print()方法将指定的数据以字符的方式传送至客户端,println()会 在送出数据之后进行换行,而print()则否,注意换行指的是在HTML原始码中设定换行字符,而不是输出<br>标签使得在网页中可以 换行。 out(JspWriter)具有缓冲区功能,HTTP的特性是为了要取得一份资源,就进行一份协议沟通,如果资源数目很多(例如一份HTML文件 还包括了许多的小图片),而每份资源的容量实际上很小,那么为了要取得完整的资源,将会花费很多通讯在协议往来上,假设如果 out(JspWriter)不具有缓冲功能,则每一次out.println(),就会直接将数据送出至客户端,那么单要完成一个完整网页的传送,就 会花费不少的网络资源,每一个JSP网页预设上都会具有缓冲,您可以使用page指令元素的autoFlush属性来设定是否使用缓冲区功能 。 在Tomcat5上,预设为每一个JSP网页备有8192字节的缓冲区(您可以使用page指令元素的buffer属性来自缓冲区的大小),在缓冲区还 没有满之前,数据不会真正被送出至客户端,在这之前,您还有机会重设送出的数据,如果缓冲区满了,数据将会被清出并送至客户 端,可以使用下面这个程序来示范: buffer.jsp 您可以使用flush()直接清出缓冲区的内容,而clearBuffer()会将缓冲区的内容清除,所以第二段文字不会出现在客户端的网页上, 而最后一段会整个JSP网页执行完整后自动送出至客户端,执行结果如下: 预设缓冲区大小:8192 这段您可以看到! 您可以使用page指令元素的autoFlush来设定JSP页面是否使用缓冲区自动清出功能,out(JspWriter)以一种方式与 HttpServletResponse的PrintWriter建立关系,两者之间的行为关系取决于是否使用缓冲区自动清出,如果使用缓冲区自动清出,则 在缓冲区满之前,或是使用flush()之前不会建立PrintWriter对象来对客户端进行输出,如果不使用缓冲区自动清出,则写入out (JspWriter)对象的数据会直接写入PrintWriter对象,然后在指定flush()之后输出至客户端。 如果您将autoFlush设定为false,则您必须明确的使用flush()来输出数据,否则缓冲区满了的话,就会发生IOException例外,使用 缓冲区有其好处,但由于缓冲区在满之前,数据并不会真正送出客户端,所以会有响应延迟的问题,如果您要实时性将结果响应至客 户端,则可以关闭缓冲区。 下面这个程序测试缓冲区关闭之后,如果缓冲区满了,会有什么结果: buffer.jsp 如果没有移开out.flush()的批注符号,则会响应一下的错误讯息: |
|