Servlet的学习之Session(1)
在学习完了Servlet中的Cookie技术后,我们再来学习另一个能保存会话数据的技术——Session。
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,注意是默认情况下,一个浏览器独占一个session,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自数据存放在各自的session中,当用户再去访问服务器的其他web资源时,其他web资源再从用户各自的session中取出数据为用户服务。
Session和Cookie的主要区别:
Cookie技术是客户端技术,是由服务器将用户的数据写回给用户浏览器的。
Session技术是服务器端技术,是把用户的数据写到服务器为用户所创建的独享的Session对象中,但Session是基于Cookie的(请看下一篇《Servlet的学习之Session(2)》)。
Session对象由服务器创建,这跟Cookie不一样。编程人员可以通过request请求对象的getSession()方法获取Session对象。
注意,Session一旦创建,是会存活无操作情况(或者浏览器关闭)下30分钟,这是由服务器(如Tomcat)来指定的。当我们关闭浏览器后,因为Session是基于cookie的,因此Session是存在的,只是我们可能无法再使用到(要看cookie是否还能取到)。
那么我们以一个简单的Session例子来说明,创建两个Servlet:分别命名为ServletDemo1和ServletDemo2。
在ServletDemo1中的代码如下:
1 HttpSession session = request.getSession(); 2 String data = "message form SessionDemo1"; 3 session.setAttribute("data", data);
在ServletDemo2中的代码如下:
1 response.setContentType("text/html;charset=utf-8"); 2 PrintWriter writer = response.getWriter(); 3 4 HttpSession session = request.getSession(); 5 String data = (String) session.getAttribute("data"); 6 writer.write(data);
当我们打开一个浏览器先访问ServletDemo1,此时浏览器会帮我们创建Session对象,并保存数据,这时再访问ServletDemo2可以看到该保存的数据:
说明Session确实能保存访问不同Servlet时的数据。
这里说清楚一点,虽然代码都是相同的,但是针对不同浏览器访问的话看到的是不同的Session对象保存的不同的数据,虽然这时候数据都是一样的。比如说A在自己主机上访问这个Servlet和B在自己电脑上访问这个相同的Servlet,A和B得到各自的Session。
而如果我们打开一个浏览器访问ServletDemo1后,再打开另一个浏览器访问ServletDemo2,那么则会显示该数据找不到:
注意:这时候是两个浏览器,即已经是两个会话了!!!
我们来做一个类似于点击商品然后能加入到购物车的案例,使用Session技术。
前提准备,我们需要为商品创建JavaBean,代码如下:
1 public class Product { 2 private String id; 3 private String name; 4 private String author; 5 6 public Product() { 7 super(); 8 } 9 10 public Product(String id, String name, String author) { 11 super(); 12 this.id = id; 13 this.name = name; 14 this.author = author; 15 } 16 17 public String getId() { 18 return id; 19 } 20 21 public void setId(String id) { 22 this.id = id; 23 } 24 25 public String getName() { 26 return name; 27 } 28 29 public void setName(String name) { 30 this.name = name; 31 } 32 33 public String getAuthor() { 34 return author; 35 } 36 37 public void setAuthor(String author) { 38 this.author = author; 39 }
然后再建立一个数据库,以类的方式来创建(谁让数据库还没学呢T_T!),然后使用Map集合来存储数据,便于通过键值对检索:
1 public class ProductDatabase { 2 3 private static Map<String,Product> map = new HashMap<String,Product>(); 4 5 static{ 6 map.put("1", new Product("1","《Java编程思想》","JB")); 7 map.put("2", new Product("2","《Java核心技术》","fdaf")); 8 map.put("3", new Product("3","《Java并发编程》","什么鬼")); 9 map.put("4", new Product("4","《Head first 设计模式》","老王")); 10 map.put("5", new Product("5","《HTML5权威手册》","hhaa")); 11 } 12 13 public static Map<String,Product> getMap() { 14 15 return map; 16 } 17 }
好了,我们在商品显示的首页显示商品,同时为每个商品建立一个超链接,以便于当用户点击超链接时能将商品的id作为存储数据的依据由其他Servlet类获取用户购买的商品种类:
1 response.setCharacterEncoding("UTF-8"); 2 response.setContentType("text/html;charset=utf-8"); 3 PrintWriter writer = response.getWriter(); 4 5 //获取数据库中的商品数据 6 Map<String, Product> map = ProductDatabase.getMap(); 7 for(Map.Entry<String, Product> entry : map.entrySet()) { 8 Product book = entry.getValue(); 9 writer.print(book.getName()+" <a href='/myservlet/servlet/BuySession?id="+book.getId()+"' >购买</a> <br/>"); 10 }
此时可以看一看效果:
接着我们来做 点击购买超链接后的Servlet,该Servlet需要将获取用户所购买的商品(通过id号),同时需要获取(创建)Session对象,并利用一个集合将所购买的商品存入,这个Session对象存储用户希望购买的商品,当我们跳转到购物车页面上时能从Session中取出商品并显示:
1 //获取用户所购买商品的id号 2 String productId = request.getParameter("id"); 3 Product book = ProductDatabase.getMap().get(productId); 4 5 //将用户所购买的商品加入到Session对象中保存,以便最后一起结账,类似于购物车功能 6 HttpSession session = request.getSession(); 7 List<Product> list = (List<Product>) session.getAttribute("productList"); 8 if(list == null){ 9 //首次购买 10 list = new ArrayList<Product>(); 11 session.setAttribute("productList", list); 12 } 13 14 list.add(book); 15 16 //跳转到购物车列表上 17 response.sendRedirect("/myservlet/servlet/CartListServlet"); 18
注意:这里使用的是sendRedirect重定向,如果使用的是forward转发,则在购物车页面进行刷新的话会将每次购买的商品再次购买。
在购物车页面的Servlet中功能就可以比较简单了,从用户的Session中取出保存的购买商品对象,并显示在页面上即可:
1 response.setCharacterEncoding("UTF-8"); 2 response.setContentType("text/html;charset=utf-8"); 3 PrintWriter writer = response.getWriter(); 4 5 writer.print("您购买的商品如下: <br/>"); 6 7 HttpSession session = request.getSession(); 8 List<Product> list = (List<Product>) session.getAttribute("productList"); 9 for(Product p : list) { 10 writer.write(p.getName()+"<br/>"); 11 }
点击多个商品,会看到在购物车的Servlet页面上会显示出我们购买的商品:
而另外开启的多个浏览器点击这些商品会看到购买的不同购物车页面,所以可以使用Session来解决不同用户来访问相同页面而同时保存他们各自不同数据的需求。
当然这只是一个简单的强调session对象能在一个会话过程中保存一个浏览器访问多个Servlet中会产生的数据,上面这样的简单示例肯定是不能用于购物的,比如当我们将浏览器关闭时(会话结束),这个session对象就结束了,那么下次再打开浏览器我们的购物车将一无所有,如果要满足用户的不同需求,那么就要了解一些session对象的底层结构,将在下一篇中介绍和学习。