51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 2176|回复: 5
打印 上一主题 下一主题

会话管理之session技术

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2018-3-5 09:46:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1. session对象

        在web开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个
浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用
户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用
户的session中取出该用户的数据,为用户服务。
        session和cookie的主要区别在于:cookie是把用户的数据写给用户的浏览器(保存在客户机);
session技术把用户的数据写到用户独占的session中(保存在服务器)。
        session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。

2. session实现原理

        浏览器A第一次访问Servlet1,服务器会创建一个session,每个session都有一个id号,创建好了
后,服务器将id号以cookie的形式回送给客户机(这些是服务器自动完成的)。当浏览器未关闭前
再次发请求访问Servlet2时,就会带着这个id号去访问服务器,这时候服务器检索下内存中有没有
与之对应的session,有就用这个session为其服务。
        如果想要关掉浏览器再打开还可以使用同一个session,则需要给服务器回送的cookie设置有
效时间(服务器自动回送的时候是没有有效期的)。具体做法是通过session对象的getId方法获得
该session的id,然后创建一个cookie,该cookie的名字为"JSESSIONID",值就是刚刚获得的id,再将
该cookie设置下有效期,(也可以设置下Path),并添加到cookie中即可。但是有效期不得超过30
分钟,因为浏览器关掉后,session只保存30分钟。

        下面通过一个案例来说明一下session的使用。

3. session的一个案例

        通过三个servlet来实现简单的购物功能:

        IndexServlet显示首页,并列出所有书(这个servlet和上一节cookie的案例中基本一致)
  1. //首页:列出所有书  
  2. public class IndexServlet extends HttpServlet {  
  3.   
  4.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  5.             throws ServletException, IOException {  
  6.          
  7.         response.setContentType("text/html;charset=UTF-8");   
  8.         PrintWriter out = response.getWriter();  
  9.          
  10.         out.write("本网站有如下书:<br/>");  
  11.          
  12.         Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();  
  13.         for(Map.Entry<String, Book> me : set) {  
  14.             Book book = me.getValue();  
  15.             out.write(book.getName() + "<a href='/test/servlet/BuyServlet?id="+book.getId()+"'>购买</a><br/>");  
  16.               
  17.         }  
  18.   
  19.     }  
  20.   
  21.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  22.             throws ServletException, IOException {  
  23.   
  24.         doGet(request, response);  
  25.     }  
  26.   
  27. }  
  28.   
  29. //写一个类来模拟数据库  
  30. class DB {  
  31.       
  32.     private static Map<String,Book> map = new LinkedHashMap();  
  33.       
  34.     //静态代码块中的内容只执行一次,该类在加载时,往map集合中put一系列书,map也需要设置为静态的  
  35.     static{  
  36.          
  37.         map.put("1", new Book("1", "javaweb开发","老张", "一本好书"));  
  38.         map.put("2", new Book("2", "spring开发","老倪", "一本好书"));  
  39.         map.put("3", new Book("3", "hibernate开发","老童", "一本好书"));  
  40.         map.put("4", new Book("4", "struts开发","老毕", "一本好书"));  
  41.         map.put("5", new Book("5", "ajax开发","老张", "一本好书"));  
  42.         map.put("6", new Book("6", "java基础","老孙", "一本好书"));  
  43.          
  44.     }  
  45.       
  46.     public static Map getAll() {  
  47.         return map;  
  48.     }     
  49. }  
  50.   
  51. class Book {  
  52.       
  53.     private String id;  
  54.     private String name;  
  55.     private String author;  
  56.     private String description;  
  57.                   
  58.     public Book() {  
  59.     }  
  60.   
  61.     public Book(String id, String name, String author, String description) {  
  62.         super();  
  63.         this.id = id;  
  64.         this.name = name;  
  65.         this.author = author;  
  66.         this.description = description;  
  67.     }  
  68.       
  69.     public String getId() {  
  70.         return id;  
  71.     }  
  72.     public void setId(String id) {  
  73.         this.id = id;  
  74.     }  
  75.     public String getName() {  
  76.         return name;  
  77.     }  
  78.     public void setName(String name) {  
  79.         this.name = name;  
  80.     }  
  81.     public String getAuthor() {  
  82.         return author;  
  83.     }  
  84.     public void setAuthor(String author) {  
  85.         this.author = author;  
  86.     }  
  87.     public String getDescription() {  
  88.         return description;  
  89.     }  
  90.     public void setDescription(String description) {  
  91.         this.description = description;  
  92.     }         
  93. }  
  94.          从上面程序中可以看出,当用户点击购买时,将书的id号带上,并跳转到BuyServlet去处理:
  95. [java] view plain copy
  96. public class BuyServlet extends HttpServlet {  
  97.   
  98.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  99.             throws ServletException, IOException {  
  100.          
  101.         String id = request.getParameter("id"); //获得url中带过来的参数id  
  102.         Book book = (Book)DB.getAll().get(id); //在DB中获得该id号的book  
  103.          
  104.         HttpSession session = request.getSession(); //获得当前session对象  
  105.         Cookie cookie = new Cookie("JSESSIONID", session.getId()); //设置新的cookie,注意cookie名必须为JSESSIONID,值为该session的id  
  106.         cookie.setMaxAge(30*60); //设置cookie有效期  
  107.         cookie.setPath("/test"); //设置cookie的路径  
  108.         response.addCookie(cookie); //将cookie添加到cookies中带给浏览器,下次浏览器访问,就会将此cookie带过来了  
  109.          
  110.         //先把书加到容器里,再把容器加到session中。一般先检查用户的session中有没有保存书的容器,没有就创建,有就加  
  111.         List list = (List)session.getAttribute("list");  
  112.         if(list == null) {  
  113.             list = new ArrayList();  
  114.             session.setAttribute("list", list);  
  115.         }  
  116.         list.add(book);  
  117.          
  118.         //跳转到显示用户买过哪些商品  
  119. //      request.getRequestDispatcher("/servlet/ListCartServlet").forward(request, response);  
  120.         response.sendRedirect("/test/servlet/ListCartServlet");  
  121.   
  122.     }  
  123.   
  124.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  125.             throws ServletException, IOException {  
  126.   
  127.         doGet(request, response);  
  128.     }  
  129. }  
复制代码
从上面的程序可以看出,当用户点击购买后,会将书的id号带过来,我们拿到id号后就可以找到相应
的书,同时我们将当前session的id保存到cookie中,再带给浏览器,这样下次浏览器访问的时候就会
将当前session的id带过来了。拿到相应的书后,放到list中,再把list放到session中,这样下次跳转的时
候,浏览器带来的cookie中有当前session的id,我们可以通过getSession()获得当前的session,再把
session中保存的list拿出来,就知道用户买了哪些书了。这就是购物车的原理,请看下面的ListCartS
ervlet:

  1. public class ListCartServlet extends HttpServlet {  
  2.   
  3.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  4.             throws ServletException, IOException {  
  5.          
  6.         response.setContentType("text/html;charset=UTF-8");   
  7.         PrintWriter out = response.getWriter();  
  8.          
  9.         HttpSession session = request.getSession(); //获得当前的session  
  10.         List<Book> list = (List)session.getAttribute("list"); //从session中拿出list  
  11.          
  12.         if(list == null || list.size() == 0) {  
  13.             out.write("对不起,您还没有购买任何商品!");  
  14.             return;  
  15.         }  
  16.          
  17.         out.write("您买过如下商品:<br/>");  
  18.         for(Book book : list) {  
  19.             out.write(book.getName() + "<br/>");  
  20.         }  
  21.   
  22.     }  
  23.   
  24.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  25.             throws ServletException, IOException {  
  26.   
  27.         doGet(request, response);  
  28.     }  
  29. }  
复制代码
4. 浏览器禁用cookie后的session处理

        由上文可知,session通过向浏览器回送cookie,如果用户将浏览器的cookie禁用了该如何解决?
        解决方案:url重写,让session的id不以cookie的形式带过来,以url中带过来。有两个url重写的方法:
  1. response.encodeRedirectURL(java.lang.String url);  //用于对sendRedirect方法后的url地址进行重写。  
  2. response.encodeURL(java.lang.String url);  //用于对表单action和超链接的url地址进行重写。  
  3. 在BuyServlet.java中,把session的id号写入cookie的几行代码去掉,将
  4. [java] view plain copy
  5. response.sendRedirect("/test/servlet/ListCartServlet");  
  6. 改为:
  7. [java] view plain copy
  8. response.sendRedirect(response.encodeRedirectURL("/test/servlet/ListCartServlet"));  
  9. 在IndexServlet.java中,把
  10. [java] view plain copy
  11. out.write(book.getName() + "<a href='/test/servlet/BuyServlet?id="+book.getId()+"'>购买</a><br/>");  
  12. 改写成:
  13. [java] view plain copy
  14. String url= "/test/servlet/BuyServlet?id=" + book.getId();  
  15. url= response.encodeURL(url);  
  16. out.write(book.getName() + "<a href='" + url + "'>购买</a><br/>");  
  17. 还有最后一步很重要:在
  18. [java] view plain copy
  19. out.write("本网站有如下书:<br/>");  
  20. 之前加上
  21. [java] view plain copy
  22. request.getSession();  
复制代码
因为要实现共享一个session,必须首先获得session。
这样就算浏览器禁用了cookie,我们依然可以共享一个session了。

5. 总结

        1. 服务器是如何做到一个session为一个浏览器的多次请求而服务的?
        服务器创建session出来后,会把session的id号以cookie的形式回写给客户机,这样,只要客户机
的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机带session的id过来
了,就会使用内存中与之对应的session为之服务。
        2. 如何做到一个session为多个浏览器服务?
        服务器第一次创建session,程序员把session的id号手动以cookie的形式回送给浏览器,并设置
cookie的有效期,这样即使用户的浏览器关了,开新的浏览器时,还会带着session的id号找服务器,
服务器从而就可以用内存中与之对应的session为第二个浏览器窗口服务。
        3. 如何做到用户禁用cookie后,session还能为多次请求而服务?
       把用户可能点击的每一个超链接后面,都跟上用户的session id号。
        4. session对象的创建和销毁时机
        用户第一次request.getSession时创建。session对象默认在30分钟没有使用,则服务器会自动
销毁session。但是用户可以在web.xml文件中手动配置session的失效时间:  下面表示1分钟失效:


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

该用户从未签到

2#
 楼主| 发表于 2018-3-5 09:46:33 | 只看该作者
<session-config>  
        <session-timeout>1</session-timeout>  
</session-config>  
        用户也可以手动调用session.invalidate方法,摧毁session。
       session就总结这么多,如有错误之处,欢迎留言指正~
回复 支持 反对

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-6 13:36 , Processed in 0.068886 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表