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

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 过多就会影响服务器了。


猜你喜欢

转载自blog.csdn.net/zjttlance/article/details/79923189
今日推荐