Servlet&JSP学习系列(2) - Request消息

Servlet是基于HTTP协议的,因而深入了解HTTP协议的消息格式,对理解Servlet有很大的帮助。事实上,HttpServletRequest就是对HTTP请求消息的一种封装。

HTTP request消息的格式如下:
[Method][SP][URI][SP][HTTP version]
[headers(key: value)]*
CRLF
[Content]

注:SP为空格
CRLF为回车换行
如:
GET /servlet/Search?Keywords=servlet+jsp HTTP/1.1
Accept:image/gif,image/jpg,*/*
Accept-Encoding:gzip
Connection:Keep-Alive
Cookie:userID=id45678
Host:localhost
User-Agent:Mozilla/4.0(compatible;MISE 6.0;Windows NT 5.0)

可以将HTTP请求消息格式分成三部分来讨论:
1. 起始行:包含请求方法(如GET、POST、PUT、DELETE等),请求URI,若是GET方法,URI中还包含了请求内容,以及HTTP版本号,一般都为HTTP/1.1的值。
2. 请求报头:包含当前请求的额外信息。如Accept表示客户端可处理的MIME类型,Cookie表示客户端传输过来的cookie值对。
3. 请求消息内容:如果是POST请求,还会在请求报头后空一行,加如请求消息的内容。(注:如要读取该内容,要用read方法,而不能用readLine方法。

一般常用的请求方法有:GET和POST。GET方法会直接在浏览器的地址栏中显示,不会加密,因而主要用于不敏感的数据,而POST的数据可以用于加密操作,主要用于敏感数据,可以加密。另外GET传送数据量较小,一般不能大于2K,而POST传送数据量较大,一般最大可以达到2M。
在servlet中,请求方法可以通过request.getMethod()方法获取。

URI表示要请求的资源,如要请求的Servlet,JSP页面,HTML页面等。如果是GET方法,则还包含了请求内容,”?”后的值对即为请求的内容,但是内容可以为空,如超链接的请求。
在servlet中,请求方法可以通过request.getRequestURI()方法获取。注:该方法获取的是URL中主机和端口之后、表单数据之前的部分,如http://somehost.com:8080/servlet/booksearch?subject=jsp,则该方法返回的值为:”/servlet/booksearch”.

HTTP版本一般有1.1、1.0。
在servlet中,可以通过request.getProtocol()获取。

请求内容:POST请求出现在请求报头后,一般也是以值对的形式出现,该值对中的值可以为二进制的数据,如文件上传操作。而GET请求则包含在URI中。请求内容一般为用户输入的数据。
在servlet中,请求的内容可以通过request.getParameter(“key”)方法获得。由于请求内容的key可以多次出现,因而对这种情况,可以通过request.getParameterValues(“key”)方法获取。同时Servlet也提供了request.getParameterNames()和request.getParameterMap()方法以获取所有值对的列表。
对GET请求,也可以通过request.getQueryString()方法来获取请求内容,如上URL返回”subject=jsp”。

或许Request消息中,最复杂的就是请求消息头了,HTTP请求消息头一般为浏览器默认填入。为什么HTTP中的请求消息中需要添加消息头呢?我的理解主要有两点:
1. 提供给服务器一些必要的信息,但是这些信息又不是由用户输入的,如cookie,host等。
2. 提供一种对HTTP协议的扩展程序,以定制基于自己的应用程序。
在servlet中,可以通过request.getHeader(“name”)获取相关的值或者用request.getDateHeader(“name”),request.getIntHeader(“name”)进行相应的类型转换,也可以通过request.getHeaderNames()获取所有的请求头列表。对多次出现的报头,可以通过getHeaders(“name”)来获取。
对几种常用的报头,servlet为其提供了专门的方法。如:
1. Cookie报头request.getCookies()
2. Authorization报头:request.getAuthType()和request.RemoteUser()的组合
3. Content-Length报头:request.getContentLength()
4. Content-Type报头:request.getContentType()

几种常见的请求报头:
1. Accept
指示客户端能够处理的MIME类型。用于某些支持多种格式的网站根据Accept报头来定制响应报文。如png文件比gif文件在压缩上占有优势,因而可以检查该报头的内容以定制返回的是png文件还是gif文件。
2. Accept-Charset
指示客户端可以使用的字符集。如ISO-8859-11。
3. Accept-Encoding
指示客户端能够处理的页面编码类型,常见的如”gzip”,”compress”等值。而响应报文中通常加入Content-Encoding来标明响应页面的编码类型。一般来说压缩的时间要比减小的传输时间要短,因而对返回页面进行压缩一般来说是值得的。
4. Accept-Language
指示客户端期望接受的语言类型(单值),如en,en-us等。该报头一般用于国际化,以处理多种语言的结果。
5. Authorization
在访问密码保护的Web页面是,客户端用于标识自己的身份。
6. Connection
指示是否保持连接,以在一个Socket中可以读取多个文件,HTTP1.1中默认为保持连接,而HTTP1.0默认相反。保持连接可以减少协商时间,增加性能。
但是不管是否保持连接,在servlet中,每一个请求多会新起一个线程来调用service方法。
7. Content-Length
只用于POST方法中,用来指示POST的数据大小,以字节为单位。
8. Cookie
向服务器返回之前服务器发送给客户端的Cookies。
9. Host
在HTTP1.1中是必须的,指示原始URL中给出的主机名和端口号。由于虚拟主机的引入(一台计算机处理多个域名对应的网站),导致服务器可能不能通过其他方式知道这个信息。
10. If-Modified-Since
指示仅当页面在制定的日志发生更改的情况下,客户程序才需要获取该页面。如果没有更新的结果,则服务器发送304报头(Not Modified)。该选项可用于浏览器有缓存的情况下。一般Servlet不需要直接处理这个报头,而是应该实现getLastModified()方法,以让系统自动处理修改的日期。
11. If-Unmodified-Since
该报头和If-Modified-Since相反,指示仅当文档比指定的日期要旧时才需要继续操作。一般来说,If-Modified-Since用在GET请求中(仅当服务器的文档比我缓存的文档要新时才获取新的文档),If-Unmodified-Since用在PUT请求中(仅当在我获得这个文档之后,服务器的文档没有其他人做过修改时,才需要更新这个文档)。这是HTTP1.1中新加入的报头。
12. Referer
指示引用Web页面的URL。如在一个Web页面1单击指向Web页面2的链接,那么在浏览器生成请求时就会将Web页面1的URL填入Referer报头中。
该报头可以用于追踪请求的来源。如可以追踪将人们引到某网站广告客户以追溯流量的来源,或者更具引用网站的不同对内容做一些调整。
要注意:
1) 客户端可以轻易的篡改Referer报头。
2) Referer的正确拼写是Referrer,这是HTTP协议作者的一个错误。
3) 某些浏览器(Opera)、广告过滤软件、个人防火墙可能会屏蔽这个报头,并且即使在正常的情况下,也只有用于点击连接时才会设置该报头,因而需要做null检查。
13. User-Agent
指示请求来源的浏览器或者其他客户端程序。可以根据该值为不同的浏览器返回不同的内容。如处理浏览器间的兼容问题。
注意:很多浏览器会在User-Agent中加入其他浏览器的内容,如果IE会加入”Mozilla”的值,以兼容JavaScript。因而需要检查某些浏览器特定包含的内容。

你可能感兴趣的:(应用服务器,Web,jsp,浏览器,servlet)