第七天:Servlet进阶——httpresponse

WEB服务器回送给WEB客户端的HTTP响应消息分为三个部分:

ü  状态行

ü  响应消息头

ü  消息正文(也叫实体内容)

今天我们就是来控制这三个部分的。

 

HTTP/1.1 200 OK   -----状态行

Server: Apache-Coyote/1.1

Content-Type: text/html          --------------------》消息响应头

Content-Length: 0

Date: Fri, 25 May 2012 03:46:22 GMT

(空一行)

实体内容在这里。

 

 

 

两种发送状态码的方式:

//     response.setStatus(//这一种只设置状态码,比较单一,可以自己指定打印出来什么。

//            404

//     );

//     response.sendError(404);//这一种不给你设置了状态码,还自动转到相应的404页面,把你的要打印的东西的缓存清空,显示自己的404.

 

 

302状态码是指我不在这了,已经搬家了,并且已在响应消息头里面要设置一个location。告诉搬到哪了,然后浏览器会重新发出请求到location返回正确的页面,这两步过程在servlet中有一个方法sendRedirect

 

response.sendRedirect("/day06_servlet_01/xxx.html");

首先:

HTTP/1.1 302 Moved Temporarily

Server: Apache-Coyote/1.1

Location:http://localhost:8888/day06_servlet_01/xxx.html

Content-Length: 0

Date: Fri, 25 May 2012 04:06:19 GMT

然后:

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Content-Type: text/html;charset=GBK

Content-Length: 315

Date: Fri, 25 May 2012 04:06:20 GMT

 

北京传智播客公司欢迎你

上面的更改状态码,讲的如何操纵消息头

 

下面讲如何操纵响应消息头。

 

设置响应消息头的方法:

       setHeader(String name,String value);可以把响应头的名字设置为任意的,但是只有你设置为正确的浏览器才会识别,才会起作用,例如:

       response.setHeader("Content-Length2","88");

       response.setHeader("Content-Length","88");

out.println("test");

我们单独设置其中一个,当设置Content-Length2时就是一个响应头,能够显示出来,不起任何作用,如果设置为Content-Length那么它起作用,因为它告诉浏览器我要88个字节,但是只传递了4个字节,那么浏览器会一直等待,直到浏览器断开链接都会结束请求,显示”test”.其实所有的都可以通过setHeader来设置,但是SUN发现有的用的太频繁了,所以单独又弄一些个新的方法。如setContentLengthsetDateHeadersetContextType

其实对响应消息头的每一个属性方法中都有单独定义:

//  response.setContentLength(4);

response.setDateHeader("Date",new Date(2012,5, 5, 5, 5).getTime());

 

极为重要的总结:

早期在serlvet中,往客户端浏览器发数据要这样写:

response.setContentType("text/html;charset=”GBK");

response.getOutputStream().write("中国".getBytes("GBK"));

第一个行,告诉浏览器我传过来是字符是按照GBK编码的,请用GBK解码,第二行,是把将要传过去的数据进行GBK编码,两者必须一致方可,如果不一致,这就是乱码产生的原因,即,先告诉别人用什么解码,然后自己再按照这个告诉别人的码去编成相应的码传递过去。如果你不指定按什么样的编码传递过去,它默认是java系统平台编码(GBK),如果你告诉浏览器以会样的方式解码,不同的浏览器有不同的默认方式,所以两者要统一,都不可少。

 

后来发现这样用的太多了,太频繁了,简化一下,不需要自己去编码了随便发

response.setContentType("text/html;charset=”GBK");

response.getWriter().println("中国");

因为第一句话,已经起了两个作用,第一、告诉客户端浏览器你要用什么样的东西解码,

第二、自己发过去的数据也按照,第一行所设置的编码方式进行编码。

 

第一行,先设置它是一种文本格式,然后再说明这种文本格式需要怎么样编码,

如果不写第二个,那么会按照ISO-8859-1编码方式,也可以用这个方法追加:

response.setCharacterEncoding("UTF-8");

如果用getWrite发送那么这一行就具有上述所说的两个作用,

第一、告诉客户端浏览器你要用什么样的东西解码,

第二、自己发过去的数据也按照,第一行所设置的编码方式进行编码。

 

一会说String.getBytes()默认按GBK(它是按照java平台默认编码方式),一会又说response.getWriter()输出的字符串默认按ISO8859-1编码(它是按照tomcat默认编码方式),

java虚拟机默认按操作系统相关的编码,tomcat默认按iso8859-1

 

禁止浏览器缓存当前文档内容:

response.setDateHeader("Expires",0);

response.setHeader("Cache-Control","no-cache"); 

response.setHeader("Pragma","no-cache");

这三种要一起用,因为不同的浏览器不一定支持哪一个。

比喻:医生给病看病,知道三服药肯定有一副能治好,但是不敢肯定是哪一副,三幅都开。

 

在之前,我们有这样一个需求,就是说服务器发过去的数据,浏览器如何知道自己用什么样的东西解码,难倒让用户去选择  查看---》编码---UTF-8\GBK等,这是不可能的,所以我们就写那个响应消息头,在那里面告诉浏览器你要用什么样的东西解码。

 

但是很显然,这样适用于动态网页,但是如果是html静态页面呢?怎么办呢?在html中有一个标签:<meta http-equiv="content-type" content="text/html; charset=UTF-8">那么浏览器在解析时间会自动按照UTF-8去解析,当然,服务器也是按照自己文件中所写的那样去编码发送的。显然,这个静态网页标签也是两个作用。

还有一个问题<meta http-equiv="content-type" content="text/html; charset=UTF-8">这行代码无论你放在哪里,放在最后它也会先被解析,这是非常重要的,你放在文本后面,它也会先被解析,所以meta标签在html先被解析。

<meta http-equiv="Refresh" content="3"/> 这个可以让静态网页刷新。

 

静态网页解决缓存:

ü  <meta http-equiv="Expires"content="0">

ü  <meta http-equiv="Cache-Control"content="no-cache">

ü  <meta http-equiv="Pragma"content="no-cache">

 

 

ü  //      //下载附件问题中英文附件只能用getOutputStream();

ü  //      Stringfilename = request.getParameter("filename");

ü  //      //以流的形式获得这个文件getResourceAsStream这个可以获得任何位置的文件,与类加载不同。

ü  //      InputStreaminputStream =this.getServletContext().getResourceAsStream("/WEB-INF/"+filename);

ü  //      //这样仅仅是把文本读取了,如何下载呢,通过设置响应消息头。

ü  //       response.setContentType("application/octet-stream");

ü  response.setHeader("Content-Disposition","attachment;filename="+filename);

ü  //     

ü  //      copyStream(inputStream,response.getOutputStream());

 

//上面是英文,如何下载带有中文文件名的呢?

我们在这里直接把中文的文件名给写死了,因为这样不会涉及到获取的问题,如果涉及到获取又是一个乱码问题,先研究一个方面。

       InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/"+"中文.txt");

      

       response.setContentType("application/octet-stream");

       response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode("中文.txt","utf-8"));

       copyStream(inputStream,response.getOutputStream());

filename="+URLEncoder.encode("中文.txt","utf-8");

句话是为什么,第一,我们上面通过response设置的编码是指响应正文内的编码方式,那么响应消息头也有字符,它是按照什么样的编码呢?难倒也是我们随意指定的吗?完全不是,浏览器的消息响应头的编码统一采用UTF-8的方式编码,所以如果我们要传递的响应消息头中有中文,那么要转换成UTF-8. attachment;filename=%E4%B8%AD%E6%96%87.txt这个就是中文两个字对应的,一个汉字对应三个。(UTF-8汉字为什么占3个字节?

 

Servlet不会接收到一个数据就发送给浏览器一个数据,只是等到缓冲区满了以后,再输送到浏览器。超过缓冲区会采用chuncked编码方式,分批传送。

Servlet程序输出的HTTP消息的响应正文首先被写入到Servlet引擎提供的一个输出缓冲区中,直到输出缓冲区被填满或者Servlet程序已经写入了所有的响应内容,缓冲区中的内容才会被Servlet引擎发送到客户端。

使用输出缓冲区后,Servlet引擎就可以将响应状态行、各响应头和响应正文严格按照HTTP消息的位置顺序进行调整后再输出到客户端。

如果在提交响应到客户端时,输出缓冲区中已经装入了所有的响应内容,Servlet引擎将计算响应正文部分的大小并自动设置Content-Length头字段。

如果在提交响应到客户端时,输出缓冲区中装入的内容只是全部响应内容的一部分, Servlet引擎将使用HTTP 1.1chunked编码方式(通过设置Transfer-Encoding头字段来指定)传输响应内容。

Servlet执行完for语句后,缓冲区满,但容器不敢肯定Servlet是否还有内容输出,所以,容器将缓冲区的内容输出给浏览器时,无法确定整个实体内容的长度,只知道当前要输出的这块内容的大小,所以它用chuncked传输方式。

 

图像访问计数器:

大家首先要知道一个网站的页面能够引用另一个网站的图像!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值