Javaweb之cookie和session

来源:互联网 发布:小米note3软件 编辑:程序博客网 时间:2024/05/17 23:53

一、会话的概念

  会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
  有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学曾经来过,这称之为有状态会话。

二、会话过程中要解决的一些问题

  每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。

三、保存会话数据的两种技术

3.1、Cookie机制

  Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。

3.2、Session机制

  session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

  当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否包含了一个session标识-称为session id,如果已经包含一个sessionid则说明以前已经为这个客户创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。

如果客户请求不包含session id,则服务器会为这个客户创建一个session并且生成一个与此session相关联的session id,这个session id将在本次响应中返回给客户端保存

3.3、Cookie机制和Session机制的区别

1、从存取方式上比较
Cookie中只能保存ASCII字符串,如果需要存取Unicode字符或者二进制数据,需要进行UTF-8GBK或者BASE64等方式的编码。Cookie中也不能直接存取Java对象。若要存储稍微复杂的信息,使用Cookie是比较困难的。
而Session中可以存取任何类型的数据,包括而不限于String、Integer、List、Map等。Session中也可以直接保存Java Bean乃至任何Java类,对象等,使用起来非常方便。可以把Session看做是一个Java容器类。
2、从隐私安全上比较
Cookie存储在客户端浏览器中,对客户端是可见的,客户端的一些程序可能会窥探、复制甚至修改Cookie中的内容。而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的危险。
如果选用Cookie,比较好的办法是,敏感的信息如账号密码等尽量不要写到Cookie中。最好是像Google、Baidu那样将Cookie信息加密,提交到服务器后再进行解密,保证Cookie中的信息只有自己能读得懂。而如果选择Session就省事多了,反正是放在服务器上,Session里任何隐私都可以。
3、从有效期上比较
Cookie能实现信息永久的保存,只需要设置CookiemaxAge属性为一个很大很大的数字或者Integer.MAX_VALUE就可以了。如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。

如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。

存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。
使用Session理论上也能实现这种效果。只要调用方法setMaxInactiveInterval(Integer. MAX_VALUE)不就可以了么。但是由于Session依赖于名为JSESSIONID的Cookie,而Cookie JSESSIONID的maxAge默认为-1,只要关闭了浏览器该Session就会失效,因此Session不能实现信息永久有效的效果。使用URL地址重写也不能实现。
而且如果设置Session的超时时间过长,服务器累计的Session就会越多,越容易导致内存溢出。
4、从对服务器的负担上比较
Session是保存在服务器端的,每个用户都会产生一个Session。如果并发访问的用户非常多,会产生非常多的Session,消耗大量的内存。因此像GoogleBaiduSina这样并发访问量极高的网站,是不太可能使用Session来追踪客户会话的。
而Cookie保存在客户端,不占用服务器资源。如果并发浏览的用户非常多,Cookie是很好的选择。对于Google、Baidu、Sina来说,Cookie也许是唯一的选择。
5、从浏览器支持上比较
Cookie是需要客户端浏览器支持的。如果客户端禁用了Cookie,或者不支持Cookie,则会话跟踪会失效。对于WAP上的应用,常规的Cookie就派不上用场了。
如果客户端浏览器不支持Cookie,需要使用Session以及URL地址重写。需要注意的是所有的用到Session程序的URL都要使用response.encodeURL(String URL)或者response.encodeRedirectURL(String URL)进行URL地址重写,否则导致Session会话跟踪失败。对于WAP应用来说,Session+URL地址重写也许是它唯一的选择。
如果客户端支持Cookie,则Cookie既可以设为本浏览器窗口以及子窗口内有效(把maxAge设为-1),也可以设为所有浏览器窗口内有效(把maxAge设为某个大于0的整数)。但Session只能在本浏览器窗口以及其子窗口内有效。如果两个浏览器窗口互不相干,它们将使用两个不同的Session。
6、从跨域名上比较
Cookie支持跨域名访问,例如将domain属性设置为".helloweenvsfei.com",则以".helloweenvsfei.com"为后缀的所有域名均可以访问该Cookie。跨域名Cookie现在被广泛用在网络中,例如GoogleBaiduSina等。而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。

四、Cookie使用范例

4.1、使用cookie记录用户上一次访问的时间

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.servlet.study;  
  2.    
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5. import java.util.Date;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.Cookie;  
  8. import javax.servlet.http.HttpServlet;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11. /** 
  12.  * cookie实例:获取用户上一次访问的时间 
  13.  */  
  14. public classCookieDemo1 extends HttpServlet {  
  15.    
  16.    publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)  
  17.             throws ServletException, IOException {  
  18.         //设置服务器端以UTF-8编码进行输出  
  19.         response.setCharacterEncoding("UTF-8");  
  20.         //设置浏览器以UTF-8编码进行接收,解决中文乱码问题  
  21.         response.setContentType("text/html;charset=UTF-8");  
  22.         PrintWriter out = response.getWriter();  
  23.         //获取浏览器访问访问服务器时传递过来的cookie数组  
  24.         Cookie[] cookies =request.getCookies();  
  25.         //如果用户是第一次访问,那么得到的cookies将是null  
  26.         if (cookies!=null) {  
  27.             out.write("您上次访问的时间是:");  
  28.             for (int i = 0; i < cookies.length; i++) {  
  29.                 Cookie cookie = cookies[i];  
  30.                 if (cookie.getName().equals("lastAccessTime")){  
  31.                     Long lastAccessTime =Long.parseLong(cookie.getValue());  
  32.                     Date date = new Date(lastAccessTime);  
  33.                     out.write(date.toLocaleString());  
  34.                 }  
  35.             }  
  36.         }else {  
  37.             out.write("这是您第一次访问本站!");  
  38.         }  
  39.          
  40.         //用户访问过之后重新设置用户的访问时间,存储到cookie中,然后发送到客户端浏览器  
  41.         Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");//创建一个cookie,cookie的名字是lastAccessTime  
  42.         //将cookie对象添加到response对象中,这样服务器在输出response对象中的内容时就会把cookie也输出到客户端浏览器  
  43.         response.addCookie(cookie);  
  44.    }  
  45.    publicvoiddoPost(HttpServletRequest request, HttpServletResponse response)  
  46.             throws ServletException, IOException {  
  47.         doGet(request, response);  
  48.    }  
  49. }  


第一次访问时这个Servlet时会提示这是您第一次访问本网站,点击浏览器的刷新按钮,进行第二次访问,此时就服务器就可以通过cookie获取浏览器上一次访问的时间了。

   在上面的例子中,在程序代码中并没有使用setMaxAge方法设置cookie的有效期,所以当关闭浏览器之后,cookie就失效了,要想在关闭了浏览器之后,cookie依然有效,那么在创建cookie时,就要为cookie设置一个有效期。如下所示:

//用户访问过之后重新设置用户的访问时间,存储到cookie中,然后发送到客户端浏览器

Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");//创建一个cookie,cookie的名字是lastAccessTime

 //设置Cookie的有效期为1天

 cookie.setMaxAge(24*60*60);

 //将cookie对象添加到response对象中,这样服务器在输出response对象中的内容时就会把cookie也输出到客户端浏览器

 response.addCookie(cookie);

  用户第一次访问时,服务器发送给浏览器的cookie就存储到了硬盘上,这样即使关闭了浏览器,下次再访问时,也依然可以通过cookie获取用户上一次访问的时间。

五、Cookie注意细节

  1. 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
  2. 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
  3. 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
  4. 如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie

 5.2、cookie中存取中文

要想在cookie中存储中文,那么必须使用URLEncoder类里面的encode(String s, String enc)方法进行中文转码,例如:

Cookie cookie = newCookie("userName", URLEncoder.encode("Cookie测试","UTF-8"));

response.addCookie(cookie);

在获取cookie中的中文数据时,再使用URLDecoder类里面的decode(String s, String enc)进行解码,例如:

URLDecoder.decode(cookies[i].getValue(),"UTF-8")

六、session使用范例

6.1、服务器是如何实现一个session为一个用户浏览器服务的?

   服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。可以用如下的代码证明:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.servlet.study;  
  2.    
  3. import java.io.IOException;  
  4. import javax.servlet.ServletException;  
  5. import javax.servlet.http.HttpServlet;  
  6. import javax.servlet.http.HttpServletRequest;  
  7. import javax.servlet.http.HttpServletResponse;  
  8. import javax.servlet.http.HttpSession;  
  9.    
  10. public classSessionDemo1 extends HttpServlet {  
  11.    
  12.    publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)  
  13.             throws ServletException, IOException {  
  14.    
  15.         response.setCharacterEncoding("UTF=8");  
  16.         response.setContentType("text/html;charset=UTF-8");  
  17.         //使用request对象的getSession()获取session,如果session不存在则创建一个  
  18.         HttpSession session = request.getSession();  
  19.         //将数据存储到session中  
  20.         session.setAttribute("data","Session测试");  
  21.         //获取session的Id  
  22.         String sessionId = session.getId();  
  23.         //判断session是不是新创建的  
  24.         if (session.isNew()) {  
  25.             response.getWriter().print("session创建成功,session的id是:"+sessionId);  
  26.         }else {  
  27.             response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);  
  28.         }  
  29.    }  
  30.    
  31.    publicvoiddoPost(HttpServletRequest request, HttpServletResponse response)  
  32.             throws ServletException, IOException {  
  33.         doGet(request, response);  
  34.    }  
  35. }  


第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的Id一起传递到服务器端了

6.2、session对象的销毁时机

  session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,例如:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xmlversionxmlversion="1.0" encoding="UTF-8"?>  
  2. <web-appversionweb-appversion="2.5"  
  3.    xmlns="http://java.sun.com/xml/ns/javaee"  
  4.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
  6.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  7.   <display-name></display-name>  
  8.   <welcome-file-list>  
  9.    <welcome-file>index.jsp</welcome-file>  
  10.   </welcome-file-list>  
  11.   <!-- 设置Session的有效时间:以分钟为单位-->  
  12.     <session-config>  
  13.         <session-timeout>15</session-timeout>  
  14.     </session-config>  
  15. </web-app>  


当需要在程序中手动设置Session失效时,可以手工调用session.invalidate方法,摧毁session。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. HttpSession session = request.getSession();  
  2. //手工调用session.invalidate方法,摧毁session  
  3. session.invalidate();  
0 0
原创粉丝点击