?
? 作者: 李翊,JAVA高级软件工程师就业班特聘讲师? blog:? (http://blog.sina.com.cn/avaj)? 
作者介绍:北京航空航天大学软件工程硕士。原IBM中国研究中心(IBM China Lab)资深系统架构师,是目前国内最著名的企业级应用设计及实现专家之一。曾经负责过的主要项目包括:Petri网实验模型系统、多个省级考试中心信息系统、河南省省级电信计费系统、国务院办公厅信息系统、企业基础信息交换平台、国产信息交换平台集成测试系统、多个基于WBI企业EAI解决方案、ePod企业级电子商务解决方案、电子政务目录交换系统等 . 
由于HTTP协议的无状态特征,Web应用中经常使用Cookie和Session来保存用户在与系统交互过程中的状态数据。下面通过分析HTTP协议对Cookie和Session的工作原理加以了解。 
一、Cookie 
Cookie的含义是“服务器送给浏览器的甜点”,即服务器在响应请求时可以将一些数据以“键-值”对的形式通过响应信息保存在客户端。当浏览器再次访问相同的应用时,会将原先的Cookie通过请求信息带到服务器端。 
下面的Servlet展示了Cookie的功能。 
? ... ... ... 
? public void doGet(HttpServletRequest request, HttpServletResponse response) 
???????????????? throws ServletException, IOException { 
????? response.setContentType("text/html"); 
????? PrintWriter out = response.getWriter(); 
????? String option = request.getParameter("option"); 
????? if ("show".equals(option)) { 
????????? //获得请求信息中的Cookie数据 
????????? Cookie[] cookies = request.getCookies(); 
????????? if (cookies != null) { 
????????????? //找出名称(键)为“cool”的Cookie 
????????????? for (int i = 0; i < cookies.length; i++) { 
????????????????? if ("cool".equals(cookies[i].getName())) { 
????????????????????? out.println("<h2>" + cookies[i].getName() + ":" 
????????????????????????? + cookies[i].getValue() + "</h2>"); 
?????????????????? } 
????????????? } 
???????? } 
????? } else if ("add".equals(option)) { 
????????? //创建Cookie对象 
????????? Cookie cookie = new Cookie("cool", "yeah!"); 
????????? //设置生命周期以秒为单位 
????????? cookie.setMaxAge(20); 
????????? //添加Cookie 
????????? response.addCookie(cookie); 
???? } 
?? ... ... ... 
该Servlet对应的url-pattern为/testCookie 
当浏览器请求地址“.../tst/testCookie?option=add”时,该Servlet创建一个Cookie对象,存储的键-值对为“cool”-“yeah”。通过response的addCookie方法将该Cookie信息添加到相应信息中。需要注意的是cookie的setMaxAge方法用于设置该cookie生命周期,单位是秒,如果过了这个期间,Cookie将失效。setMaxAge方法的参数如果为负值则表示该Cookie将在浏览器关闭时过期,如果参数为0则表示立刻删除该Cookie。访问该地址,对应的请求和响应的HTTP信息为: 
请求: 
GET /tst/testCookie?option=add HTTP/1.1 
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, ** 
Accept-Language: zh-cn 
UA-CPU: x86 
Accept-Encoding: gzip, deflate 
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1) 
Host: 192.168.5.100:8080 
Connection: Keep-Alive 
Cookie: cool=yeah! 
响应: 
HTTP/1.1 200 OK 
Server: Apache-Coyote/1.1 
Content-Type: text/html;charset=ISO-8859-1 
Content-Length: 21 
Date: Sun, 29 Jun 2008 06:15:26 GMT 
<h2>cool:yeah!</h2> 
注意,请求协议头中用于携带cookie信息的格式。 
Cookie可以用于保持用户的会话状态,但Cookie信息保存在客户端,存在较大的安全隐患,且一般浏览器对Cookie的数目及数据大小有严格的限制。在Web应用中,一般情况下通过HttpSession对象保持会话状态。 
二、Session 
Session对象的原理在于,服务器可以为客户端创建并维护一个所谓的Session对象,用于存放数据。在创建Session对象的同时,服务器将会为该Session对象产生一个唯一编号,这个编号称之为SessionID,服务器以Cookie的方式将SessionID存放在客户端。当浏览器再次访问该服务器时,会将SessionID作为Cookie信息带到服务器,服务器可以通过该SessionID检索到以前的Session对象,并对其进行访问。需要注意的是,此时的Cookie中仅仅保存了一个SessionID,而相对较多的会话数据保存在服务器端对应的Session对象中,由服务器来统一维护,这样一定程度保证了会话数据安全性,但增加了服务器端的内存开销。 
存放在客户端的用于保存SessionID的Cookie会在浏览器关闭时清除。我们把用户打开一个浏览器访问某个应用开始,到关闭浏览器为止交互过程称为一个“会话”。在一个“会话”过程中,可能会向同一个应用发出了多次请求,这些请求将共享一个Session对象,因为这些请求携带了相同的SessionID信息。 
1. Session工作原理 
下面的Servlet用来演示Session的工作原理: 
... ... ... 
public void doGet(HttpServletRequest request, HttpServletResponse response) 
?? throws ServletException, IOException { 
??? response.setContentType("text/html"); 
??? PrintWriter out = response.getWriter(); 
??? String option = request.getParameter("option"); 
??? if ("create".equals(option)) { 
??????? //获得HttpSession对象 
??????? HttpSession session = request.getSession(); 
??????? //设置Session对象的最长不活动间隔 
??????? session.setMaxInactiveInterval(30); 
??????? //获取Session中的数据 
??????? List list = (List) 
