上一节我们总结了cookie技术,这节主要总结一下session技术。

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的案例中基本一致)

//首页:列出所有书
public class IndexServlet extends HttpServlet {  public void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  response.setContentType("text/html;charset=UTF-8");   PrintWriter out = response.getWriter();  out.write("本网站有如下书:<br/>");  Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();  for(Map.Entry<String, Book> me : set) {  Book book = me.getValue();  out.write(book.getName() + "<a href='/test/servlet/BuyServlet?id="+book.getId()+"'>购买</a><br/>");  }  }  public void doPost(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  doGet(request, response);  }  }  //写一个类来模拟数据库
class DB {  private static Map<String,Book> map = new LinkedHashMap();  //静态代码块中的内容只执行一次,该类在加载时,往map集合中put一系列书,map也需要设置为静态的  static{  map.put("1", new Book("1", "javaweb开发","老张", "一本好书"));  map.put("2", new Book("2", "spring开发","老倪", "一本好书"));  map.put("3", new Book("3", "hibernate开发","老童", "一本好书"));  map.put("4", new Book("4", "struts开发","老毕", "一本好书"));  map.put("5", new Book("5", "ajax开发","老张", "一本好书"));  map.put("6", new Book("6", "java基础","老孙", "一本好书"));  }  public static Map getAll() {  return map;  }
}  class Book {  private String id;  private String name;  private String author;  private String description;  public Book() {  }  public Book(String id, String name, String author, String description) {  super();  this.id = id;  this.name = name;  this.author = author;  this.description = description;  }  public String getId() {  return id;  }  public void setId(String id) {  this.id = id;  }  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public String getAuthor() {  return author;  }  public void setAuthor(String author) {  this.author = author;  }  public String getDescription() {  return description;  }  public void setDescription(String description) {  this.description = description;  }
}  

从上面程序中可以看出,当用户点击购买时,将书的id号带上,并跳转到BuyServlet去处理:

public class BuyServlet extends HttpServlet {  public void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  String id = request.getParameter("id"); //获得url中带过来的参数id  Book book = (Book)DB.getAll().get(id); //在DB中获得该id号的book
          HttpSession session = request.getSession(); //获得当前session对象  Cookie cookie = new Cookie("JSESSIONID", session.getId()); //设置新的cookie,注意cookie名必须为JSESSIONID,值为该session的id  cookie.setMaxAge(30*60); //设置cookie有效期  cookie.setPath("/test"); //设置cookie的路径  response.addCookie(cookie); //将cookie添加到cookies中带给浏览器,下次浏览器访问,就会将此cookie带过来了  //先把书加到容器里,再把容器加到session中。一般先检查用户的session中有没有保存书的容器,没有就创建,有就加  List list = (List)session.getAttribute("list");  if(list == null) {  list = new ArrayList();  session.setAttribute("list", list);  }  list.add(book);  //跳转到显示用户买过哪些商品
//      request.getRequestDispatcher("/servlet/ListCartServlet").forward(request, response);  response.sendRedirect("/test/servlet/ListCartServlet");  }  public void doPost(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  doGet(request, response);  }
}  

从上面的程序可以看出,当用户点击购买后,会将书的id号带过来,我们拿到id号后就可以找到相应的书,同时我们将当前session的id保存到cookie中,再带给浏览器,这样下次浏览器访问的时候就会将当前session的id带过来了。拿到相应的书后,放到list中,再把list放到session中,这样下次跳转的时候,浏览器带来的cookie中有当前session的id,我们可以通过getSession()获得当前的session,再把session中保存的list拿出来,就知道用户买了哪些书了。这就是购物车的原理,请看下面的ListCartServlet:

public class ListCartServlet extends HttpServlet {  public void doGet(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  response.setContentType("text/html;charset=UTF-8");   PrintWriter out = response.getWriter();  HttpSession session = request.getSession(); //获得当前的session  List<Book> list = (List)session.getAttribute("list"); //从session中拿出list  if(list == null || list.size() == 0) {  out.write("对不起,您还没有购买任何商品!");  return;  }  out.write("您买过如下商品:<br/>");  for(Book book : list) {  out.write(book.getName() + "<br/>");  }  }  public void doPost(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {  doGet(request, response);  }
}  

4. 浏览器禁用cookie后的session处理

由上文可知,session通过向浏览器回送cookie,如果用户将浏览器的cookie禁用了该如何解决?
        解决方案:url重写,让session的id不以cookie的形式带过来,以url中带过来。有两个url重写的方法:

response.encodeRedirectURL(java.lang.String url);  //用于对sendRedirect方法后的url地址进行重写。
response.encodeURL(java.lang.String url);  //用于对表单action和超链接的url地址进行重写。  

在BuyServlet.java中,把session的id号写入cookie的几行代码去掉,将

response.sendRedirect("/test/servlet/ListCartServlet");  

改为:

response.sendRedirect(response.encodeRedirectURL("/test/servlet/ListCartServlet"));  

在IndexServlet.java中,把

out.write(book.getName() + "<a href='/test/servlet/BuyServlet?id="+book.getId()+"'>购买</a><br/>");  

改写成:

String url= "/test/servlet/BuyServlet?id=" + book.getId();
url= response.encodeURL(url);
out.write(book.getName() + "<a href='" + url + "'>购买</a><br/>");  

还有最后一步很重要:在

out.write("本网站有如下书:<br/>");  

之前加上

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分钟失效:

<session-config>  <session-timeout>1</session-timeout>
</session-config>  

用户也可以手动调用session.invalidate方法,摧毁session。

session就总结这么多,如有错误之处,欢迎留言指正~

转载于:https://www.cnblogs.com/shanheyongmu/p/5922666.html

会话管理之session技术相关推荐

  1. 【移动网络】5GC:5G核心网络的会话管理(Session Management)

    Session Management SMF的功能 基本的PDU会话连接 PDU会话建立 隧道与传输连接 PDUs Type SSC (Service and Session Continuity) ...

  2. Servlet之会话管理4个技术

    由于HTTP的无状态性,使得会话管理或者会话跟踪成为Web应用开发一个无法避免的 问题. 会话可以简单的理解为客户端用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器的整个过 ...

  3. 会话管理:Session与Cookie

    1. 导言 HTTP 是一种无状态协议,每次客户端访问Web页面时,客户端打开一个单独的浏览器窗口连接到Web服务器,由于服务器不会自动保存之前客户端请求的相关信息,所以无法识别一个HTTP请求是否为 ...

  4. Java中的会话管理– HttpServlet,Cookie,URL重写

    Session Management in Java Servlet Web Applications is a very interesting topic. Session in Java Ser ...

  5. 浅谈电商网站开发中用户会话管理机制的设计和实现原理

    笔者由于工作需要,最近对国内外两款知名的电商网站的用户会话管理(User Session Management) 的实现机制做了一些调研,这里把我学习到的一些知识分享给各位同行,希望起到抛砖引玉的作用 ...

  6. spring security 会话管理

    目录 一.会话管理(Session) 1.获取用户信息身份 2.会话控制 3.会话超时 4.会话并发控制 5.集群 session 二.RememberMe 实现 RememberMe 源码分析 三. ...

  7. javaweb:会话管理和保存会话数据的两种技术(Cookie、Session)

    会话: •会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 会话过程中要解决的一些问题? •每个用户与服务器进行交互的过程中,各自 ...

  8. PHP会话管理——Session和Cookie

    会话管理包括:Session和Cookie,主要功能都是把客户端和服务器关联起来,用于管理和查看用户在网站中的状态. 背景 Web应用程序是使用HTTP协议传输数据的.HTTP协议是无状态的协议.一旦 ...

  9. datastore_使用Spring Session和JDBC DataStore进行会话管理

    datastore 在Web应用程序中,用户会话管理对于管理用户状态至关重要. 在本文中,我们将学习在集群环境中管理用户会话所采用的方法,以及如何使用Spring Session以更简单和可扩展的方式 ...

最新文章

  1. 【网络流】解题报告: luogu P2045 方格取数加强版(k取方格数)(最大费用最大流)
  2. 梯度的直观理解_梯度下降最直观的理解
  3. J-Link 输出供电问题
  4. ubuntu 开发板ping通虚拟机挂载nfs服务器
  5. grasp设计模式应用场景_grasp设计模式笔记回顾
  6. Docker快速搭建Bugzilla
  7. python中if函数的使用方法_(for i in range) (else) (if)使用方法
  8. sleep() wait() yield() join()
  9. 剑指Offer之扑克牌顺子
  10. [导入]十大经典误会
  11. C++.Net在Release方式下单步调试时需要修改一些设置,否则变量会有错位或乱码,切记!...
  12. Juggling Life and Learning
  13. 联想计算机怎么开启网络共享,联想笔记本开启Wi-Fi共享图文教程
  14. unity3d 坦克大战实战
  15. kail 安装小企鹅输入法
  16. 安装谷歌插件,程序包无效,解决方法
  17. JEECG集成flowable
  18. 【火影之卡卡西动漫主题】
  19. 头哥 (Educoder)数据结构与算法实验:实验11 TYJ动态规划
  20. win10 Bat脚本获取管理员权限

热门文章

  1. 【深度学习入门到精通系列】CIFAR-10数据集说明
  2. 【django轻量级框架】云端系统之Django框架
  3. 快速排序 java 实现
  4. java 填充pdf_Java如何创建和填充PDF表单域(代码示例)
  5. python趣味编程100_《Python游戏趣味编程》 第8章 勇闯地下一百层
  6. 视图插入数据_带切片器的数据透视图
  7. 电脑主板维修_自学电脑主板维修第45讲
  8. phpexecl保存mysql_【PHP】将数据库表保存为Excel(PHPExcel)
  9. spi iic和串口的区别_GMII、SGMII和SerDes的区别和联系
  10. html得到画布的颜色的值,从画布上获取像素颜色