5.1.2 设置响应消息头
在HttpServletResponse接口中定义了若干设置HTTP响应消息头的方法,如addHeader方法可以添加响应消息头字段;addIntHeader方法可以添加整数值的响应消息头字段;setContextType方法可以设置Context-Type字段值。
HTTP响应消息头是由若干key-value对组成的,其中key表示字段名,value表示字段值,中间用冒号(:)分隔。如下面的内容就是一个标准的HTTP响应消息头:
Content-Length: 1024
Content-Type: text/html
Content-Location: http://nokiaguy.blogjava.net
Accept-Ranges: bytes
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Tue, 30 Dec 2008 11:49:53 GMT
从上面的内容可以看出,每一行都由一个字段和字段值组成,字段和字段值之间用冒号分隔(如Content-Length: 1024)。当使用Servlet向客户端发送响应消息时,为了完成某个功能或动作,如通知浏览器使用何种字符集显示网页;指定响应正文的类型等,需要对某些响应消息头进行设置。这就需要使用下面设置响应消息头的方法:
1. addHeader与setHeader方法
addHeader和setHeader方法可用于设置HTTP响应消息头的所有字段。这两个方法的定义如下:
public void addHeader(String name, String value);
public void setHeader(String name, String value);
其中name表示响应消息头的字段名,value表示响应消息头的字段值。这两个方法都会向响应消息头增加一个字段。但它们的区别是如果name所指的字段名已经存在,setHeader方法会用value来覆盖旧的字段值,而addHeader会增加一个同名的字段(HTTP响应消息头允许存在多个同名的字段)。在设置时,name不区分大小写。如设置Content-Type时可使用下面两行代码中的任意一行:
response.setHeader("Content-Type", "image/png");
response.setHeader("content-type", "image/png");
2. addIntHeader与setIntHeader方法
HttpServletResponse接口定义了两个专门设置整型字段值的方法,这两个方法的定义如下:
public void addIntHeader(String name, int value);
public void setIntHeader(String name, int value);
这两个方法与setHeader和addHeader方法类似。它们在设置整型字段值时避免了将int类型转换为String类型的麻烦。
3. addDateHeader与setDateHeader方法
HttpServletResponse接口定义了两个专门设置日期字段值的方法,这两个方法的定义如下:
public void addDateHeader(String name, long date);
public void setDateHeader(String name, long date);
这两个方法与setHeader和addHeader方法类似。HTTP响应消息头中的日期一般为GMT时间格式。这两个方法在设置日期字段值时省去了将自1970年1月1日 0 点 0分 0秒开始计算的一个以毫秒为单位的长整数值转换为GMT时间字符串的麻烦。
4. setContentType方法
setContentType方法用于设置Servlet的响应正文的MIME类型,对于HTTP协议来说,就是设置Content-Type字段的值。如响应正文是png格式的图形数据,就需要使用该方法将响应正文的MIME类型设置成“image/png”,代码如下:
response.setContentType("image/png");
关于更详细的MIME类型消息,可以在<Tomcat安装目录>\conf\web.xml文件中找到。setContentType方法还可指定响应正文所使用的字符集类型,如“text/html; charset=UTF-8”,在设置字符集类型时,charset应为小写,否则不起作用。如果在MIME类型中未指定字符集编码类型,并且使用getWriter方法(将在后面的部分介绍)返回的PrintWriter对象输出文本时,Tomcat将使用ISO8859-1字符集编码格式对输出的文本进行编码。因此,如果在Servlet中要向客户端输出中文时,应使用setContentType方法设置响应正文的字符集编码。
5. setCharacterEncoding方法
该方法设置了Content-Type字段的字符集部分,也就是设置“text/html; charset=UTF-8”中的“charset=UTF-8”部分。在使用setCharacterEncoding方法之前,如果Content-Type字段不存在,必须使用setContentType或setHeader方法添加Content-Type字段,否则setCharacterEncoding方法字符集类型不会出现在响应消息头上。setCharacterEncoding方法同时还设置了使用PrintWriter对象向客户端输出的字符的编码格式,这一点和setContextType方法类似。
6. setContentLength方法
setContentLength方法用于设置响应正文的大小(单位是字节)。对于HTTP协议来说,这个方法就是设置Content-Length字段的值。当使用下载工具下载文件时,会发现在每个下载文件的状态栏中都会显示文件大小,其实这个值就是从Content-Length字段中获得。如果下载某些文件时,无法正确显示文件大小,说明HTTP响应消息头中并未设置Content-Length字段的值。一般来说,在Servlet中并不需要使用setContentLength方法设置Content-Length的值,因为Servlet引擎会根据向客户端实际输出的响应正文的大小动态设置Content-Length字段的值。
7. containsHeader方法
containsHeader方法用于检查某个字段名是否在HTTP响应消息头中存在,如果存在,返回true,否则返回false。containsHeader方法的定义如下:
public boolean containsHeader(String name);
8. setLocale方法
该方法设置了响应消息的本地信息。setLocale方法的定义如下:
public void setLocale(java.util.Locale loc);
其中Locale对象包含了语言和国家地区信息。该方法有以下三个作用:
(1)设置Content-Language字段的值,该字段表示当前页面所使用的语言。如设置成zh-CN,表示当前页面是中文。
(2)设置Content-Type字段的字符集编码部分。但如果Content-Type字段不存在,则该方法不会自动添加Content-Type字段,也就是说,要想使用setLocale方法设置字符集编码,必须将使用addHeader方法或其他可以添加响应字段的方法添加一个Content-Type字段,才可以使用setLocale方法设置Content-Type字段的字符集编码部分,如下面的代码所示:
response.addHeader("content-type", "");
response.setLocale(new java.util.Locale("zh", "CN"));
response.getWriter().println("设置Content-Type字段的字符集编码部分");
由于java.util.Locale类并未包含字符集编码信息,因此,如果要使用setLocale方法设置Content-Type字段值的字符集编码部分,还必须在web.xml文件中使用<local-encoding-mapping-list>元素进行映射,代码如下:
<locale-encoding-mapping-list>
<locale-encoding-mapping>
<locale>zh-CN</locale>
<encoding>UTF-8</encoding>
</locale-encoding-mapping>
</locale-encoding-mapping-list>
上面的配置代码将zh-CN映射成了UTF-8,因此,使用setLocale方法将Content-Language字段设置成zh-CN后,Content-Type字段值的字符集编码部分就会被设置成“charset=UTF-8”。
(3)设置要输出到客户端的文本的编码格式。
在SevletResponse和HttpServletResponse接口中有很多方法可以设置Content-Type字段的字符集编码部分和服务端输出文本的编码格式,这些方法包括addHeader、setHeader、setContent-Type、setCharacterEncoding、setLocale。实际上,这些方法具有同等的地位,也就是说,后面调用的方法将覆盖前面调用的方法的设置。但这些方法必须在调用getWriter方法之前调用,否则设置不会生效。