Servlet学习笔记(七):Session详解

本文详细介绍了Session的工作原理、实现方式、创建及生命周期等内容,并对比了Session与Cookie的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Servlet学习笔记(七):Session详解

原创  2014年10月12日 20:02:21

Session是服务器端技术,服务器在运行时可以为每个用户的浏览器创建一个其独享的Session对象,由于Session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的资源放在各自的Session中,当用户再去访问服务器中的其他web资源时,其他web资源再从用户各自的Session中取出数据为用户服务。


一、Session基础知识


1、工作原理:

Cookie类似于检查客户身上的“通行证”来确定客户身份的话,那么 Session 机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。


2、实现方式。

1)通过 Cookie 实现——将Session的 ID 放入 Cookie。

A、Session 的实现需要使用Cookie作为识别标志。Session 不能依据 HTTP 连接判断是否为同一个客户,因此服务器向客户端发送一个名为JSESSIONID的 Cookie ,它的值为该Session的ID。Sessin依据该Cookie来识别是否为同一用户。


这边的JSESSIONID只是个名字,可以随便修改的。配置服务器的<Context  sessionCookieName=" XXX ">设置。


B、该Cookie 为服务器自动生成的,它的 maxAge属性一般为 -1,表示仅当前浏览器内有效(包括字窗口),关闭浏览器失效,各浏览器不共享。


这会是一个问题,当你关闭浏览器,在重开,就会是另一个Cookie。解决办法:服务器在创建Session的时候回写一个同名的Cookie,并设置maxAge值即可,注意有path(见下图)

[java]  view plain  copy
  1. // 解决自动生成的cookie为临时性问题,回写一个同名Cookie回去  
  2. Cookie cookie = new Cookie("JSESSIONID",session.getId());         
  3. cookie.setMaxAge(session.getMaxInactiveInterval());  
  4. cookie.setPath(this.getServletContext().getContextPath());  
  5. response.addCookie(cookie);  


C、注意:第一次访问的时候,因为JSESSIONID是放在Cookie中,伴随浏览器访问传入,所以第一次访问的时候是没有的。request.getRequestedSessionId() 返回为空。这点在Firefox试验是没问题的。但是Chrome中会有出入。


Firefox在第一次访问的时候,请求信息中是没有 JSESSIONID数据的,请求结束,服务器返回。如下:




但是,Chrome在第一次访问的时候,请求中即会有一个临时的JSESSIONID,然后返回一个。如下:




问题:

有一种解释为:第一次访问的时候,在你的程序第一次访问服务器的时候,服务端并不知道你的客户端浏览器是否支持cookie,因此,当你第一次请求发起的时候,服务端会默认url重写,也就是将session id写到url中传递。

或者只是浏览器的支持问题?暂时没解决。


2)通过URL 重写实现——将Session的 ID 重写到URL地址中。

A、针对客户端不支持Cookie的情况,可以通过 URL 重写实现Session 。

B、response.encodeURL(String url)实现 URL 地址的重写。如果重定向可以这么写:response.sendRedirect(response.encodeRedirectURL("/"))

[java]  view plain  copy
  1. // 通过 重写URL实现  
  2. response.encodeURL("/");  
  3. response.encodeRedirectURL("/");  
  4. response.sendRedirect(response.encodeRedirectURL("/"));  


C、可以在服务器配置,取消重写的功能。配置Tomcat 的<Context  disableURLRewriting="true">即可。


3、Session 的 创建

封装在javax.servlet.http.HttpSession 对象中,可以通过request.getSession()获取。

[java]  view plain  copy
  1. HttpSession session = request.getSession();//不存在,返回空  
  2. HttpSession session = request.getSession(true);//不存在,新建一个  

4、Session 的ID。

[java]  view plain  copy
  1. String sessionId = session.getId();  

5、 Session 的时间。

1)有效期。

[java]  view plain  copy
  1. // 3-1 有效期  
  2. // get/set MaxInactiveInterval可以设置和获取session的有效期  单位为 秒  
  3. // 也可以通过 <session-config>标签配置在web.xml中 ,单位为分钟  
  4. // tomcat自身的config/web.xml 默认配置session有效期为 30 分钟  
  5. // 如通过setMaxInactiveInterval设置过有效时间,这段代码注掉,时间还是不会改变。  
  6.   
  7. session.setMaxInactiveInterval(1000 * 5);  
  8. int time = session.getMaxInactiveInterval();  


2)创建时间。

[java]  view plain  copy
  1. // 3-2 创建时间  
  2. long createTime = session.getCreationTime();//返回long  
  3. Date createDate = new Date(createTime);  
  4. logger.debug("Session创建的时间为 : " + formatDate(createDate));  

3)最近访问时间。

[java]  view plain  copy
  1. // 3-3 最近访问时间  
  2. // 客户端只要访问服务器,不管有没有读写session,服务器都会更新最近访问时间,并维护本session  
  3. long accessedTime = session.getLastAccessedTime();//返回long  
  4. Date accessedDate = new Date(accessedTime);  
  5. logger.debug("Session最近访问的时间为 : " + formatDate(accessedDate));  


6、Session路径

Session 在客户端对应同一个窗口,没有路径访问问题,同一个servletContext 下的servlet/jsp共享同一个Session 。前提是同一个客户端窗口。



二、Session 的生命周期


1)Session在用户第一次访问服务器的时候自动创建。只有访问JSP、Servlet等程序才会创建Session(是访问到getSession()代码时), 只访问 HTML、 等静态资源并不会创建Session。 如果尚未生成Session ,也可以使用request.getSession(true)强制生成。


2)Session生成后,只要用户继续访问,服务器就会更新Session 的最后访问时间,并维护该 Session 。用户每访问服务器一次,无论是否读写 Session ,服务器都认为该用户的 Session “活跃(active)”了一次。


3)关闭浏览器,不会让 Session 结束,Session 是服务器管理的,只有当 session.invalidate() 代码或者配置好的有效时间<session-comfig>到了,Session 才会结束。



三、Session的常用方法。




四、测试代码如下:

[java]  view plain  copy
  1. package servlet.session;  
  2.   
  3. import java.io.IOException;  
  4. import java.text.SimpleDateFormat;  
  5. import java.util.Date;  
  6.   
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.http.HttpServlet;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11. import javax.servlet.http.HttpSession;  
  12.   
  13. import org.apache.log4j.Logger;  
  14. /** 
  15.  *  
  16.  * BaseSession.java 
  17.  * 
  18.  * @title Session 
  19.  * @description 
  20.  * @author SAM-SHO  
  21.  * @Date 2014-10-12 
  22.  */  
  23. public class BaseSession extends HttpServlet {  
  24.   
  25.     private static final long serialVersionUID = 1L;  
  26.       
  27.     private Logger logger = Logger.getLogger(this.getClass());  
  28.   
  29.   
  30.     public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  31.         this.doPost(request, response);  
  32.     }  
  33.   
  34.   
  35.     public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  36.           
  37.         //    
  38.         boolean isValid = request.isRequestedSessionIdValid();  
  39.         logger.debug("请求带过来的session是否有效 : " + isValid);  
  40.           
  41.         // 第一次访问的时候 firefox 为空,而chrome 确是有值的,但是和下面创建的session不是同一个  
  42.         String seesionId = request.getRequestedSessionId();  
  43.         logger.debug("request获取的SessionID : " + seesionId);  
  44.           
  45.         boolean isFromCookie = request.isRequestedSessionIdFromCookie();  
  46.         boolean isFromUrl = request.isRequestedSessionIdFromURL();  
  47.         logger.debug("是否是通过Cookie实现: "  + isFromCookie + " | 是否是通过URL实现: " + isFromUrl);  
  48.   
  49.           
  50.           
  51.         // 1-Session的创建  
  52. //      HttpSession session = request.getSession();//不存在,返回空  
  53.         HttpSession session = request.getSession(true);//不存在,新建一个  
  54.           
  55.         logger.debug("获取到的Session 为 : " + session.getClass().getName());  
  56.           
  57.         // 2-Session的ID  
  58.         String sessionId = session.getId();  
  59.         logger.debug("创建的 Session的ID 为 : " + sessionId);  
  60.           
  61.         // 3-session的时间:三个时间构成了session 的生命周期  
  62.           
  63.         // 3-1 有效期  
  64.         // get/set MaxInactiveInterval可以设置和获取session的有效期  单位为 秒  
  65.         // 也可以通过 <session-config>标签配置在web.xml中 ,单位为分钟  
  66.         // tomcat自身的config/web.xml 默认配置session有效期为 30 分钟  
  67.         // 如通过setMaxInactiveInterval设置过有效时间,这段代码注掉,时间还是不会改变。  
  68.           
  69.         session.setMaxInactiveInterval(1000 * 5);  
  70.         int time = session.getMaxInactiveInterval();  
  71.         logger.debug("Session的有效期 为 : " + time);  
  72.           
  73.           
  74.         // 3-2 创建时间  
  75.         long createTime = session.getCreationTime();//返回long  
  76.         Date createDate = new Date(createTime);  
  77.         logger.debug("Session创建的时间为 : " + formatDate(createDate));  
  78.           
  79.         // 3-3 最近访问时间  
  80.         // 客户端只要访问服务器,不管有没有读写session,服务器都会更新最近访问时间,并维护本session  
  81.         long accessedTime = session.getLastAccessedTime();//返回long  
  82.         Date accessedDate = new Date(accessedTime);  
  83.         logger.debug("Session最近访问的时间为 : " + formatDate(accessedDate));  
  84.           
  85.           
  86.         // 4-常用方法  
  87.           
  88.         // 4-1设置 Attribute 是key-value类型  
  89.         // key为String 类型, value为 Object 。可以放置javaBean。比Cookie强大。  
  90.           
  91.         session.setAttribute("userName""Sam-Sho");  
  92.         String userName = (String) session.getAttribute("userName");          
  93.         logger.debug("Session中放置的数据   : " + userName);  
  94.           
  95.         session.removeAttribute("userName");  
  96.           
  97.         // 4-2 让session失效  
  98.         session.invalidate();  
  99.   
  100.           
  101.         // 4-3 其他与session有关的一些方法          
  102.         String seesionId2 = request.getRequestedSessionId();//  
  103.         logger.debug("request获取的SessionID 2: " + seesionId2);  
  104.           
  105.         boolean isFromCookie2 = request.isRequestedSessionIdFromCookie();  
  106.         boolean isFromUrl2 = request.isRequestedSessionIdFromURL();  
  107.         logger.debug("是否是通过Cookie实现2: "  + isFromCookie2 + " | 是否是通过URL实现2: " + isFromUrl2);  
  108.   
  109. //      // 通过 重写URL实现  
  110. //      response.encodeURL("/");  
  111. //      response.encodeRedirectURL("/");  
  112. //      response.sendRedirect(response.encodeRedirectURL("/"));  
  113.   
  114.   
  115.     }  
  116.       
  117.     /** 
  118.      * 简单转换时间 
  119.      * @param date 
  120.      * @return 
  121.      */  
  122.     private String formatDate(Date date){  
  123.         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");  
  124.         String strDate = format.format(date);         
  125.         return strDate;  
  126.           
  127.     }  
  128.   
  129. }  
【输出】

[java]  view plain  copy
  1. [JavaWeb] [2014-10-12 11:54:08,345] [DEBUG] [MyFilter:40] - 上下文路径:/JavaWeb  
  2. [JavaWeb] [2014-10-12 11:54:08,345] [DEBUG] [MyFilter:41] - 访问的servlet或者jsp的路径 : /servlet/BaseSession  
  3. [JavaWeb] [2014-10-12 11:54:08,348] [DEBUG] [BaseSession:31] - 请求带过来的session是否有效 : false  
  4. [JavaWeb] [2014-10-12 11:54:08,348] [DEBUG] [BaseSession:35] - request获取的SessionID : 9B582560CB3588E3205030C0B9A9E1D7  
  5. [JavaWeb] [2014-10-12 11:54:08,348] [DEBUG] [BaseSession:39] - 是否是通过Cookie实现: true | 是否是通过URL实现: false  
  6. [JavaWeb] [2014-10-12 11:54:08,361] [DEBUG] [BaseSession:47] - 获取到的Session 为 : org.apache.catalina.session.StandardSessionFacade  
  7. [JavaWeb] [2014-10-12 11:54:08,364] [DEBUG] [BaseSession:51] - 创建的 Session的ID 为 : 95698550D17BB0465D6EC43179A984DB  
  8. [JavaWeb] [2014-10-12 11:54:08,364] [DEBUG] [BaseSession:63] - Session的有效期 为 : 1200  
  9. [JavaWeb] [2014-10-12 11:54:08,364] [DEBUG] [BaseSession:69] - Session创建的时间为 : 2014-10-12 11:54:08  
  10. [JavaWeb] [2014-10-12 11:54:08,365] [DEBUG] [BaseSession:75] - Session最近访问的时间为 : 2014-10-12 11:54:08  
  11. [JavaWeb] [2014-10-12 11:54:08,367] [DEBUG] [BaseSession:85] - Session中放置的数据   : Sam-Sho  
  12. [JavaWeb] [2014-10-12 11:54:08,389] [DEBUG] [BaseSession:96] - request获取的SessionID 2: 9B582560CB3588E3205030C0B9A9E1D7  
  13. [JavaWeb] [2014-10-12 11:54:08,389] [DEBUG] [BaseSession:100] - 是否是通过Cookie实现2true | 是否是通过URL实现2false  


五、Session 和 Cookie 的比较。


1、从存取方式上比较:

1)Cookie 中只能存ASCII字符串,其他需要编码。不能直接存 java 对象。

2)Session 中可以存取任何类型的数据,直接保存JavaBean。


2、从隐私安全上比较

1)Cookie存储在客户端,会存在风险。所以一般一些敏感信息,如密码等尽量不要放入 Cookie,并且对Cookie 信息加密。提交到服务器在解密,保证安全性。

2)Session 存储在服务器,安全多了。


3、从有效期上比较

1)Cookie 的有效期只要设置Cookie 的maxAge即可。

2)Session 如果设置的有效期过长,会导致服务器累计的 Session 过多,导致内存溢出。


4、从对服务器负担上比较

1)Cookie无负担,所以比如大型的网站,电商等都会使用Cookie 追踪客户会话。

2)Session 过多就会影响服务器了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值