好文档 - 专业文书写作范文服务资料分享网站

黑马程序员javaweb教程:HttpServletResponse的输出问题

天下 分享 时间: 加入收藏 我要投稿 点赞

HttpServletResponse的输出问题

1 response的输出流

response对象有getWriter()和getOutputStream()两个方法,它们都是用来向客户端响应用的流对象,不过一个是字符流,另一个是字节流。

? PrintWriter getWriter():获取响应字符流,用来向客户端响应二进制数据,例如图

片;

? ServletOutputStream getOutputStream():获取响应字节流,用来向客户端响应文本

数据,例如HTML代码。

这两者之前只能使用其中一个,也就是说,要么使用字符流,要么使用字节流,不能两者兼得。如果在获取其中一个流对象后,再去获取另一个流,那么就会出现异常。 PrintWriter pw = response.getWriter(); OutputStream out = response.getOutputStream();//抛出异常 OutputStream out = response.getOutputStream(); PrintWriter pw = response.getWriter();//抛出异常 2 刷新输出流

response内部的输出流有8KB的缓冲区,如果缓冲区满了的话,那么response会自动去提交,即把缓冲区内容输出给客户端。这时调用response的isCommited()方法返回的就是true,表示response已经提交过至少一次了。

也可以在缓冲区没有装满时调用response.flushBuffer()方法刷新输出流,把缓冲区中的数据发送到客户端去。同样,这也会导致response的isCommited()方法返回的就是true,表示response已经提交过至少一次了。

其实也可以调用response.getWirter().flush()方法达到与调用response.flushBuffer()相同的效果。这两种方式基本相同!

一旦response的isCommited()方法返回true,这说明服务器已经至少把状态码、响应头等数据发送给客户端了,也就是说已经开始向客户响应了。 response.setContentType(\); PrintWriter out = response.getWriter(); out.print(\大家好\); out.flush();//或者是response.flushBuffer(); System.out.println(\);//可以在这里添加断点,进行测试。但只有FireFox可以看到效果! 但是,这里你要注意一下,不是说服务器向客户端发送了数据,就表示数据一定会显示在浏览器上。因为客户端的浏览器也许会有自己的缓存,在浏览器的缓存没有满之前,浏览器是不会去显示的。例如IE8和Google浏览器就是这样,但FireFox会马上显示数据!

测试得到IE8的缓存为16KB,只要响应数据大于16KB就会在IE8上显示出来。 response.setContentType(\);

for(int i = 0; i < 1024 * 16 + 1; i++) { } System.out.println(\); //可以在本行添加断点,进行测试 response.getWriter().print(\); 重定向

1 什么是重定向

重定向与请求转发很相似,但有本质上的区别。请求转发需要使用RequestDispatcher类的forward()方法,而重定向需要使用response对象的sendRedirect()方法。

// AServlet public void doGet(HttpServletRequest request, HttpServletResponse response) } // BServlet public void doGet(HttpServletRequest request, HttpServletResponse response) } throws ServletException, IOException { response.setContentType(\); PrintWriter out = response.getWriter(); out.print(\); throws ServletException, IOException { response.sendRedirect(\);

2 重定向的原理

现在你应该已经会用重定向了,但你还不知道重定向的原理。我们先来说说重定向的原理,然后再去与请求转发比较。

response.sendRedirect()方法其实就是向客户端的响应!没错,调用这个方法就已经是向客户端响应了。那你可能会问,为什么响应了之后又会看到BServlet的响应结果呢?因为状态码为302,这表示命令客户端浏览器马上再去向服务器发出另一个请求,请求的资源为BServlet。

当响应状态码为302时,响应头信息中需要还有一个响应头信息,这个头信息名为Location。这相当于你到我家来找我,我家门上有个纸条,上面写着“302,我已经搬家,请马上到XXX来,可以找到我”。302表示“以搬家”,而XXX表示“新地址”。其中响应头信息Location就是“新地址”了。

请求AServlet

请求BServlet

没错,重定向其实就是两个请求,而且两个请求还是连续的,因为速度很快,所以你看不出这是两个请求。

你也许已经留意到了,浏览器的地址栏中显示的不在是AServlet,而是BServlet。你可以尝试去访问http://www.sun.com,但最终浏览器地址栏中显示的是http://www.oracle.com/us/sun/index.htm。这就是重定向!

因为是两个请求,所以你在AServlet中使用request.setAttribute()保存的数据,在BServlet中是获取不到的!这一点与请求转发是不同的!

3 重定向与请求转发的比较

重定向的理解:你到我家找我借钱(第一个请求),但是我已经搬家,新住户把我的新地址告诉了你(服务器返回302响应,以及Location响应头),你再去新地址找我(第二个请求),我把钱借给了你(第二个响应,200)。 重定向时序图

注意一下,重定向其实一共是两个请求。因为是两个请求,所以不能使用request在两个请求中间传递数据!!!(两个HTTP请求,不能使用request.setAttribute()和request.getAttribute()传递数据)。因为服务器会为每个请求创建新的request和response对象!

观察浏览器地址栏中的地址会发生变化,这是因为浏览器重定向到新的地址了。 第二个请求一定是GET,不可能是POST!!!因为只有提交POST表单才是POST请求,而第二个请求是浏览器通过第一个请求的响应结果直接发出的,所以一定是GET。所以调用的一定是BServlet的doGet()方法。

请求转发的理解:你到我家找我借钱(第一个请求),但是我已经搬家,新住户让你稍等,然后新住户去我的新地址把我找来(请求转发),然后我们见面了,我把钱借给了你。(响应成功,200)

请求转发时序图

因为只有一个请求,所以request对象可以重用!可以在BServlet中使用

request.getAttribute()或request.getParameter()。

因为只有一个请求,所以浏览器地址栏中还是原来的AServlet。也就是说,浏览器根本就不知道AServlet去请BServlet完成的请求。

如果客户端一开始发出的是GET请求,那么调用的是AServlet的doGet()方法,转发到BServlet还是GET请求(因为只有一个请求),所以调用的也是BServlet的doGet()方法;如果客户端一开始发出的是POST请求,那么调用的就是AServlet的doPost()方法,转发到BServlet还是POST请求,所以调用的还是BServlet的doPost()方法。

结论:

? 重定向:两个请求;请求转发:一个请求;

? 重定向:不能共享request和response;请求转发:可以共享request和response; ? 重定向:浏览器地址栏发生变化;请求转发:浏览器地址栏不发生变化;

? 重定向:调用目标servlet的doGet()方法;请求转发:由发出请求的方法决定到底

调用目标servlet的哪个方法;

? 重定向:可以跳转到百度;请求转发:只能在当前上下文内容跳转。

4 什么时候用重定向,什么时候用请求转发

其实这个问题很简单,如果需要有共享数据时,那么就使用请求转发。如果不需要使用共享数据时,那么就使用重定向!

request.setAttribute(“hello”, “world”); 如果你想这样做,说明需要希望在跳转到下一个Servlet时可以通过request.getAttribute()来获取数据,这时就必须使用请求转发了。

5 重定向、请求转发,与response响应的关系

注意,下面介绍的是重定向和请求转发的一个共同点!所以这里就不在区分重定向和请求转发了。

无论是重定向还是请求转发,都是把工作委派给目标Servlet(BServlet)来完成。所以在原Servlet(AServlet)中就不要使用response去响应(response.getWriter().println(“hello”))!!!

假如你在AServlet中做了响应(response.getWriter().println(“hello”)),然后跳转(重定向或请求转发)到BServlet,那么你不会看到在AServlet中做的响应(hello)。因为在跳转(重定向或请求转发)时,Tomcat会把response的响应流中的数据“清空”!!!

黑马程序员javaweb教程:HttpServletResponse的输出问题

HttpServletResponse的输出问题1response的输出流response对象有getWriter()和getOutputStream()两个方法,它们都是用来向客户端响应用的流对象,不过一个是字符流,另一个是字节流。?PrintWritergetWriter():获取响应字符流,用来向客户
推荐度:
点击下载文档文档为doc格式
5x7zh7m04t8uhsm07tfq670et7c1ze0175r
领取福利

微信扫码领取福利

微信扫码分享