客户请求的处理:HTTP请求报头

创建高效的servlet的关键之一,就是要了解如何操纵HTTP超文本传输协议。

请求报头是指浏览器发送到服务器的HTTP信息,它不同于前面提到的表单数据,它是有浏览器间接设定的的。

一个典型的HTTP请求如下,它可能是用户向位于http://www.somebookstore.com/servlet/Search的servlet提交书籍搜索时产生的:

GET /servlet/Search?keywords=servlets+jsp HTTP/1.1
Accept: image/gif, image/jpg, */*
Accept-Encoding: gzip
Connection: Keep-Alive
Cookie: userID=id456578

Host: www.somebookstore.com
Referer: http://www.somebookstore.com/findbooks.html
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)


请求报头的内容是关于这个请求的一些信息。

报头名称----报头的值



5.1 请求报头的读取

只需调用HttpServletRequest的getHeader方法即可返回当前请求指定的报头(String类型的或者null)

如:request.getHeader("connection"),即得到connection报头的内容

尽管getHeader是读取报头的通用方式,但由于几种报头使用很普遍,HttpServletRequest提供了专门的访问方法:

getCookies

返回Cookie报头的内容,存储在由Cookie对象构成的数组中

getAuthType 和getRemoteUser

对Authorization报头进行拆分,分解成各个组成部分

getContentLength

返回Content-Length报头的值(int类型)

getContentType

返回Content-Type报头的值,(String类型)

getDateHeader 和getIntHeader

读取指定的报头,并转化为Date和int值

getHeaderNames

得到一个Enumeration,枚举当前请求中所有的报头名称

getHeaders

对于一个出现多次的报头名称,用此方法得到一个Enumeration,枚举这个报头所有的值

getMethod

返回主请求方法

getRequestURI

返回请求的这个URL中主机端口之后,表单数据之前的部分,例如:http://randomhost.com/servlet/search.BookSearch?subject=jsp

返回/servlet/search.BookSearch

getQueryString

返回表单数据,同样以上述URL为例,返回subject=jsp

getProtocol

返回HTTP协议的版本





5.2 示例:创建一个表格,读取它所接收到的所有报头以及报头的值

调用request.getHeaderNames得到所有报头名字的一个Enumeration,然后迭代。

1 package coreservlets;
2
3  import java.io.*;
4  import javax.servlet.*;
5  import javax.servlet.http.*;
6  import java.util.*;
7
8
9  public class ShowRequestHeaders extends HttpServlet {//servlet继承自HttpServlet
10   public void doGet(HttpServletRequest request,
11 HttpServletResponse response)//doGet的两个参数
12   throws ServletException, IOException {
13 response.setContentType("text/html");//输出的格式
14   PrintWriter out = response.getWriter();//输出out
15   String title = "Servlet Example: Showing Request Headers";
16 String docType =
17 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +
18 "Transitional//EN\">\n";
19 out.println(docType +
20 "<HTML>\n" +
21 "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n" +
22 "<BODY BGCOLOR=\"#FDF5E6\">\n" +
23 "<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" +
24 "<B>Request Method: </B>" +
25 request.getMethod() + "<BR>\n" +//请求方法
26   "<B>Request URI: </B>" +//URL
27   request.getRequestURI() + "<BR>\n" +
28 "<B>Request Protocol: </B>" +//协议版本
29   request.getProtocol() + "<BR><BR>\n" +
30 "<TABLE BORDER=1 ALIGN=\"CENTER\">\n" +
31 "<TR BGCOLOR=\"#FFAD00\">\n" +
32 "<TH>Header Name<TH>Header Value");
33 Enumeration headerNames = request.getHeaderNames();//全部报头的枚举
34   while(headerNames.hasMoreElements()) {
35 String headerName = (String)headerNames.nextElement();//每一个报头名
36   out.println("<TR><TD>" + headerName);
37 out.println(" <TD>" + request.getHeader(headerName));//request.getHeader(headerName),每个报头的值
38   }
39 out.println("</TABLE>\n</BODY></HTML>");
40 }
41
42
43 //在doPost里调用doGet
44   public void doPost(HttpServletRequest request,
45 HttpServletResponse response)
46 throws ServletException, IOException {
47 doGet(request, response);
48 }
49 }

去请求这个servlet:http://localhost:8080/Servlet/servlet/ShowRequestHeaders




5.3 了解HTTP1.1 请求报头

了解HTTP1.1最常见的几种报头的意义

报头名:

Accept   浏览器或者其他客户程序能处理的MIME类型

Accept-Charset  浏览器可以使用的字符集

Accept-Encoding  编码类型

Accept-Language  语言


Authorization  在访问密码保护的页面时,客户用这个报头表示自己的身份

Connection  客户能否处理连续性的HTTP连接

Content-Length  只是用于POST请求,给出POST数据的大小

Cookie  向服务器返回cookie,这些cookie是之前由服务器发送给浏览器的

Host  原始url的主机名和端口号

If-Modified-Since  仅当页面在指定日期之后发生更改的情况下,客户程序才希望获取该页面

If-Unmodified-Since  与上相反

Referer  表明引用web页面的url,即你是从哪个页面链接到这个页面来的

User-Agent  标识生成请求的浏览器或其他客户程序,可以根据这个为不同的浏览器返回不同的内容





5.4  示例:发送压缩的web页面---Accept-Encoding

Accept-Encoding报头中指出了当前浏览器是否支持gzip编码,对于支持gzip编码的浏览器而言,发送压缩的web页面可以大大提高性能,压缩页面在网络上传输流量更小,在浏览器端在自动解压缩并以正常方式生成结果。

对于支持gzip的情况,使用GZIPOutputStream来输出即可


if (GzipUtilities.isGzipSupported(request) &&
!GzipUtilities.isGzipDisabled(request)) {
out
= GzipUtilities.getGzipWriter(response);//只是输出流不一样而已
response.setHeader("Content-Encoding", "gzip");
}
else {
out
= response.getWriter();
}



判断是否支持gzip的方法:

public static boolean isGzipSupported
(HttpServletRequest request) {
String encodings
= request.getHeader("Accept-Encoding");
return((encodings != null) &&
(encodings.indexOf(
"gzip") != -1));
}


public static boolean isGzipDisabled
(HttpServletRequest request) {
String flag
= request.getParameter("disableGzip");
return((flag != null) && (!flag.equalsIgnoreCase("false")));
}




5.5  示例:区分不同的浏览器类型---User-Agent

可以从报头User-Agent中得到浏览器类型的相关信息,由此可为不同的浏览器返回不同的内容:

String userAgent = request.getHeader("User-Agent");
if ((userAgent != null) &&
(userAgent.indexOf(
"MSIE") != -1)) {
title
= "Microsoft Minion";
message
= "Welcome, O spineless slave to the " +
"mighty empire.";
}
else {
title
= "Hopeless Netscape Rebel";
message
= "Enjoy it while you can. " +
"You <I>will</I> be assimilated!";
}




5.6  示例:根据客户的到达方式定制页面 ---Referer


Referer报头指出,用户单击连接到达当前页面时所处页面的位置。如果用户直接输入页面地址,那么浏览器就不会发送Referer,request.getHeader("Referer")为null。

你可以这样来得到refer的内容:

String referer = request.getHeader("Referer");//请求这个servlet之前所在的页面的url

根据这个url可以来判断这个url是否包含某些字符,以此来做不同的显示

if (contains(referer, "JRun")) {
imageName
= "jrun-powered.gif";
}
else if (contains(referer, "Resin")) {
imageName
= "resin-powered.gif";
}
else {
imageName
= "tomcat-powered.gif";
}



从而在后面的程序中根据请求的来源(是从哪个页面链接过来的)显示不同的图片。






5.7  标准CGI变量的访问


servlet中CGI变量的等价物,了解




这一章主要讲述了什么是http请求报头,以及几个常见的报头的用法,这几个报头的应用

posted @ 2011-04-11 19:47  jinmengzhe  阅读(4400)  评论(0编辑  收藏  举报