HTTP简介
WEB浏览器与WEB服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议。HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议集中的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程以及数据本身的格式。
HTTP协议的版本: HTTP/1.0、HTTP/1.1、HTTP-NG
HTTP 的会话方式 浏览器访问多图网页的过程
浏览器与WEB服务器的连接过程是短暂的,每次连接只处理一个请求和响应。对每一个页面的访问,浏览器与WEB服务器都要建立一次单独的连接。浏览器到WEB服务器之间的所有通讯都是完全独立分开的请求和响应对。
HTTP请求消息与响应消息
请求消息的结构:一个请求行、若干消息头、以及实体内容,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。
一个使用GET方式的请求消息中不能包含实体内容,只有使用POST、PUT和DELETE方式的请求消息中才可以包含实体内容。
响应消息的结构:一个状态行、若干消息头、以及实体内容 ,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。
响应消息的实体内容就是网页文件的内容,也就是在浏览器中使用查看源文件的方式所看到的内容。
HTTP消息头
1>使用消息头,可以实现HTTP客户机与服务器之间的条件请求和应答,消息头相当于服务器和浏览器之间的一些暗号指令。
2>每个消息头包含一个头字段名称,然后依次是冒号、空格、值、回车和换行符。
3>消息头字段名是不区分大小写的,但习惯上将每个单词的第一个字母大写。
4>整个消息头部分中的各行消息头可按任何顺序排列。
5>消息头又可以分为通用信息头、请求头、响应头、实体头等四类。
6>许多请求头字段都允许客户端在值部分指定多个可接受的选项,多个项之间以逗号分隔。
7>有些头字段可以出现多次。
请求行与状态行
请求行
格式:请求方式 资源路径 HTTP版本号<CRLF> 举例:GET /test.html HTTP/1.1
请求方式:POST、HEAD、OPTIONS、DELETE、TRACE、PUT
状态行
格式: HTTP版本号 状态码 原因叙述<CRLF> 举例:HTTP/1.1 200 OK
使用GET和POST方式传递参数
在URL地址后面可以附加一些参数 举例:http://www.it315.org/servlet/ParamsServlet?param1=abc¶m2=xyz
GET方式:
1)当用户在浏览器地址栏中直接输入某个url地址或者单击网页上一个超链接时,浏览器使用get方式发送请求。
2)当网页行的form标单的method属性设定为"GET",或者没有设置method属性(默认为GET),提交表单时,浏览器也用get方式发送请求。
使用GET请求方式给WEB服务器传递参数的格式:http://www.it315.org/counter.jsp?name=zhangsan&password=123
使用GET方式传送的数据量一般限制在1KB以下。
GET /servlet/ParamsServlet?param1=abc¶m2=xyz HTTP/1.1
POST方式:
1)POST请求方式主要用于向WEB服务器端程序提交FORM表单中的数据,当网页行的form标单的method属性设定为"POST"时,提交表单时,浏览器使用post方式发送请求。
2)POST方式将各个表单字段元素及其数据作为HTTP消息的实体内容发送给WEB服务器,传送的数据量要比使用GET方式传送的数据量大得多。
<form>表单元素的enctype属性用于指定浏览器使用哪种编码方法将表单中的数据传送给WEB服务器,该属性可以有两种取值:
application/x-www-form-urlencoded multipart/form-data
POST /servlet/ParamsServlet HTTP/1.1 Host: Content-Type: application/x-www-form-urlencoded Content-Length: 28 param1=abc¶m2=xyz
get方式和post方式的区别:
使用get方式提交表单时,浏览器将各个表单字段元素及其数据按照url参数的方式附加在请求行的资源后面。使用get方式传递的数据量是有限的,一般限制在1K以下。
使用post方式时,浏览器把各表单字段元素及其数据作为HTTP消息的实体内容发送给web服务器,而不是作为url地址参数传递,因此,使用post方式,要比使用get方式大的多。
1>get是从服务器上获取数据,post是向服务器传送数据。
2>在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交。
3>对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
4>GET方式提交的数据最多只能有1024字节,而POST则没有此限制。
5>安全性问题。正如在1>中提到,使用Get的时候,参数会显示在地址栏上,而Post不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用post为好。
响应状态码
响应状态码用于表示服务器对请求的各种不同处理结果和状态,它是一个三位的十进制数。响应状态码可归为5种类别,使用最高位为1到5来进行分类,如下所示:
(1)100~199表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 。(2)200~299表示成功接收请求并已完成整个处理过程 。(3)300~399为完成请求,客户需进一步细化请求。例如,请求的资源已经移动一个新地址。(4)400~499客户端的请求有错误。(5)500~599服务器端出现错误。
200(正常)表示一切正常,返回的是正常请求结果。206(部分内容)客户发送了一个带有Range头(要求服务器只返回文档中的部分内容)的GET请求,服务器按要求完成了这个请求。302/307(临时重定向)指出被请求的文档已被临时移动到别处,此文档的新的URL在Location响应头中给出。304(未修改)表示客户机缓存的版本是最新的,客户机应该继续使用它。
401(未经授权)表示客户机访问的是一个受口令和密码保护的页面,结合使用一个WWW-Authenticate响应头提示客户机应重新发出一个带有Authorization头的请求消息。404(找不到)服务器上不存在客户机所请求的资源。500(内部服务器错误)服务器端的CGI、ASP、JSP等程序发生错误。
通用信息头
通用信息头字段既能用于请求消息,也能用于响应消息,它包括一些与被传输的实体内容没有关系的常用消息头字段。
Cache-Control: no-cache Connection: close/Keep-Alive Date: Tue, 11 Jul 2014 18:23:51 GMT Pragma: no-cache Trailer: Date Transfer-Encoding: chunked Upgrade: HTTP/2.0, SHTTP/1.3 Via: HTTP/1.1 Proxy1, HTTP/1.1 Proxy2 Warning: any text
请求头
请求头字段用于客户端在请求消息中向服务器传递附加信息,主要包括客户端可以接受的数据类型、压缩方法、语言、以及发出请求的超链接所属网页的URL地址等信息。
Accept: text/html,image/* Accept-Charset: ISO-8859-1,unicode-1-1 Accept-Encoding: gzip,compress Accept-Language: en-gb,zh-cn Authorization: Basic enh4OjEyMzQ1Ng== Expect: 100-continue From: [email protected] Host: www.it315.org:80 If-Match: "xyzzy", "r2d2xxxx" If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT If-None-Match: "xyzzy", "r2d2xxxx" If-Range: Tue, 11 Jul 2000 18:23:51 GMT If-Unmodified-Since: Tue, 11 Jul 2000 18:23:51 GMT Max-Forwards: 1 Proxy-Authorization: Basic enh4OjEyMzQ1Ng== Range: bytes=100-599 Range: bytes=100- Range: bytes=-100 Referer: http://www.it315.org/index.jsp TE: trailers,deflate User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
响应头
响应头字段用于服务器在响应消息中向客户端传递附加信息,包括服务程序名,被请求资源需要的认证方式,被请求资源已移动到的新地址等信息。
Accept-Range: bytes Age: 315315315 Etag: b38b9-17dd-367c5dcd Location: http://www.it315.org/index.jsp Proxy-Authenticate: BASIC realm="it315" Retry-After: Tue, 11 Jul 2000 18:23:51 GMT Server: Microsoft-IIS/5.0 Vary: Accept-Language WWW-Authenticate: BASIC realm="it315"
实体头
实体头用作实体内容的元信息,描述了实体内容的属性,包括实体信息类型、长度、压缩方法、最后一次修改时间、数据有效期等。
Allow: GET,POST Content-Encoding: gzip Content-Language: zh-cn Content-Length: 80 Content-Location: http://www.it315.org/java_cn.html Content-MD5: ABCDABCDABCDABCDABCDAB== Content-Range: bytes 2543-4532/7898 Content-Type: text/html; charset=GB2312 Expires: Tue, 11 Jul 2000 18:23:51 GMT Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT
扩展头
在HTTP消息中,也可以使用一些在HTTP 1.1正式规范里没有定义的头字段,这些头字段统称为自定义的HTTP头或扩展头,它们通常被当作是一种实体头处理。现在流行的浏览器实际上都支持Cookie、Set-Cookie、Refresh和Content-Disposition等几个常用的扩展头字段。
//Refresh头字段 Refresh: 1 Refresh: 1;url=http://www.it315.org //Content-Disposition头字段 Content-Type: application/octet-stream Content-Disposition: attachment; filename=aaa.zip
问题
HTTP协议是一种无状态的协议,WEB服务器本身不能识别出哪些请求是同一个浏览器发出的 ,浏览器的每一次请求都是完全孤立的。即使 HTTP1.1 支持持续连接,但当用户有一段时间没有提交请求,连接也会关闭。
怎么才能实现网上商店中的购物车呢:某个用户从网站的登录页面登入后,再进入购物页面购物时,负责处理购物请求的服务器程序必须知道处理上一次请求的程序所得到的用户信息。
作为 web 服务器,必须能够采用一种机制来唯一地标识一个用户,同时记录该用户的状态。
会话和会话状态
WEB应用中的会话是指一个客户端浏览器与WEB服务器之间连续发生的一系列请求和响应过程。WEB应用的会话状态是指WEB服务器与浏览器在会话过程中产生的状态信息,借助会话状态,WEB服务器能够把属于同一会话中的一系列的请求和响应过程关联起来。
实现有状态的会话
WEB服务器端程序要能从大量的请求消息中区分出哪些请求消息属于同一个会话,即能识别出来自同一个浏览器的访问请求,这需要浏览器对其发出的每个请求消息都进行标识:属于同一个会话中的请求消息都附带同样的标识号,而属于不同会话的请求消息总是附带不同的标识号,这个标识号就称之为会话ID(SessionID)。在 Servlet 规范中,常用以下两种机制完成会话跟踪Cookie和Session。
cookie机制
Cookie机制采用的是在客户端保持 HTTP 状态信息的方案。
Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在HTTP响应消息头中附带传送给浏览器的一个小文本文件。一旦WEB浏览器保存了某个Cookie,那么它在以后每次访问该WEB服务器时,都会在HTTP请求头中将这个Cookie回传给WEB服务器。
底层的实现原理: WEB服务器通过在HTTP响应消息中增加Set-Cookie响应头字段将Cookie信息发送给浏览器,浏览器则通过在HTTP请求消息中增加Cookie请求头字段将Cookie回传给WEB服务器。
一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
在Servlet程序中使用Cookie
Servlet API中提供了一个javax.servlet.http.Cookie类来封装Cookie信息,它包含有生成Cookie信息和提取Cookie信息的各个属性的方法。
//Cookie类的方法: //构造方法: public Cookie(String name,String value) getName方法 setValue与getValue方法 setMaxAge与getMaxAge方法 setPath与getPath方法
HttpServletResponse接口中定义了一个addCookie方法,它用于在发送给浏览器的HTTP响应消息中增加一个Set-Cookie响应头字段。
HttpServletRequest接口中定义了一个getCookies方法,它用于从HTTP请求消息的Cookie请求头字段中读取所有的Cookie项。
cookie的发送
1>.创建Cookie对象
2>.设置最大时效
3>.将Cookie放入到HTTP响应报头
如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie; 存储在浏览器的内存中,用户退出浏览器之后被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。发送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一个 Set-Cookie HTTP响应报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创建新的报头,因此将这个方法称为是addCookie,而非setCookie。
会话cookie和持久cookie的区别
如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。
cookie的读取
1>.调用request.getCookies,要获取浏览器发送来的cookie,需要调用HttpServletRequest的getCookies方法,这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。
2>.对数组进行循环,调用每个cookie的getName方法,直到找到感兴趣的cookie为止.
使用cookie属性的注意问题
属性是从服务器发送到浏览器的报头的一部分;但它们不属于由浏览器返回给服务器的报头。因此除了名称和值之外,cookie属性只适用于从服务器输出到客户端的cookie;服务器端来自于浏览器的cookie并没有设置这些属性。
Session机制
Session机制采用的是在服务器端保持 HTTP 状态信息的方案 。
服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否包含了一个session标识(即sessionId),如果已经包含一个sessionId则说明以前已经为此客户创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。如果客户请求不包含sessionId,则为此客户创建一session 并且生成一个与此session相关联的sessionId,这个session id将在本次响应中返回给客户端保存。