会话管理之session技术
上一节我们总结了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技术相关推荐
- 【移动网络】5GC:5G核心网络的会话管理(Session Management)
Session Management SMF的功能 基本的PDU会话连接 PDU会话建立 隧道与传输连接 PDUs Type SSC (Service and Session Continuity) ...
- Servlet之会话管理4个技术
由于HTTP的无状态性,使得会话管理或者会话跟踪成为Web应用开发一个无法避免的 问题. 会话可以简单的理解为客户端用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器的整个过 ...
- 会话管理:Session与Cookie
1. 导言 HTTP 是一种无状态协议,每次客户端访问Web页面时,客户端打开一个单独的浏览器窗口连接到Web服务器,由于服务器不会自动保存之前客户端请求的相关信息,所以无法识别一个HTTP请求是否为 ...
- Java中的会话管理– HttpServlet,Cookie,URL重写
Session Management in Java Servlet Web Applications is a very interesting topic. Session in Java Ser ...
- 浅谈电商网站开发中用户会话管理机制的设计和实现原理
笔者由于工作需要,最近对国内外两款知名的电商网站的用户会话管理(User Session Management) 的实现机制做了一些调研,这里把我学习到的一些知识分享给各位同行,希望起到抛砖引玉的作用 ...
- spring security 会话管理
目录 一.会话管理(Session) 1.获取用户信息身份 2.会话控制 3.会话超时 4.会话并发控制 5.集群 session 二.RememberMe 实现 RememberMe 源码分析 三. ...
- javaweb:会话管理和保存会话数据的两种技术(Cookie、Session)
会话: •会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 会话过程中要解决的一些问题? •每个用户与服务器进行交互的过程中,各自 ...
- PHP会话管理——Session和Cookie
会话管理包括:Session和Cookie,主要功能都是把客户端和服务器关联起来,用于管理和查看用户在网站中的状态. 背景 Web应用程序是使用HTTP协议传输数据的.HTTP协议是无状态的协议.一旦 ...
- datastore_使用Spring Session和JDBC DataStore进行会话管理
datastore 在Web应用程序中,用户会话管理对于管理用户状态至关重要. 在本文中,我们将学习在集群环境中管理用户会话所采用的方法,以及如何使用Spring Session以更简单和可扩展的方式 ...
最新文章
- 【网络流】解题报告: luogu P2045 方格取数加强版(k取方格数)(最大费用最大流)
- 梯度的直观理解_梯度下降最直观的理解
- J-Link 输出供电问题
- ubuntu 开发板ping通虚拟机挂载nfs服务器
- grasp设计模式应用场景_grasp设计模式笔记回顾
- Docker快速搭建Bugzilla
- python中if函数的使用方法_(for i in range) (else) (if)使用方法
- sleep() wait() yield() join()
- 剑指Offer之扑克牌顺子
- [导入]十大经典误会
- C++.Net在Release方式下单步调试时需要修改一些设置,否则变量会有错位或乱码,切记!...
- Juggling Life and Learning
- 联想计算机怎么开启网络共享,联想笔记本开启Wi-Fi共享图文教程
- unity3d 坦克大战实战
- kail 安装小企鹅输入法
- 安装谷歌插件,程序包无效,解决方法
- JEECG集成flowable
- 【火影之卡卡西动漫主题】
- 头哥 (Educoder)数据结构与算法实验:实验11 TYJ动态规划
- win10 Bat脚本获取管理员权限
热门文章
- 【深度学习入门到精通系列】CIFAR-10数据集说明
- 【django轻量级框架】云端系统之Django框架
- 快速排序 java 实现
- java 填充pdf_Java如何创建和填充PDF表单域(代码示例)
- python趣味编程100_《Python游戏趣味编程》 第8章 勇闯地下一百层
- 视图插入数据_带切片器的数据透视图
- 电脑主板维修_自学电脑主板维修第45讲
- phpexecl保存mysql_【PHP】将数据库表保存为Excel(PHPExcel)
- spi iic和串口的区别_GMII、SGMII和SerDes的区别和联系
- html得到画布的颜色的值,从画布上获取像素颜色