zoukankan      html  css  js  c++  java
  • Servlet 学习笔记8:会话

    会话状态概述 

      HTTP协议的无状态Stateless)特点带来了一系列的问题。特别是通过在线商店购物时,服务器不能顺利地记住以前的事务就成了严重的问题。它使得购物篮之类的应用很难实现:当我们把商品加入购物篮时,服务器如何才能知道篮子里原先有些什么?即使服务器保存了上下文信息,我们仍旧会在电子商务应用中遇到问题。例如,当用户从选择商品的页面(由普通的服务器提供)转到输入信用卡号和送达地址的页面(由支持SSL的安全服务器提供),服务器如何才能记住用户买了些什么? 

      这个问题一般有三种解决方法: 

      Cookie。利用HTTP Cookie来存储有关购物会话的信息,后继的各个连接可以查看当前会话,然后从服务器的某些地方提取有关该会话的完整信息。这是一种优秀的,也是应用最广泛的方法。然而,即使Servlet提供了一个高级的、使用方便的Cookie接口,仍旧有一些繁琐的细节问题需要处理: 

      从其他Cookie中分别出保存会话标识的Cookie 

      为Cookie设置合适的作废时间(例如,中断时间超过24小时的会话一般应重置)。 

      把会话标识和服务器端相应的信息关联起来。(实际保存的信息可能要远远超过保存到Cookie的信息,而且象信用卡号等敏感信息永远不应该用Cookie来保存。) 

      改写URL。你可以把一些标识会话的数据附加到每个URL的后面,服务器能够把该会话标识和它所保存的会话数据关联起来。这也是一个很好的方法,而且还有当浏览器不支持Cookie或用户已经禁用Cookie的情况下也有效这一优点。然而,大部分使用Cookie时所面临的问题同样存在,即服务器端的程序要进行许多简单但单调冗长的处理。另外,还必须十分小心地保证每个URL后面都附加了必要的信息(包括非直接的,如通过Location给出的重定向URL)。如果用户结束会话之后又通过书签返回,则会话信息会丢失。 

      隐藏表单域。HTML表单中可以包含下面这样的输入域:<INPUT TYPE="HIDDEN" NAME="session" VALUE="...">。这意味着,当表单被提交时,隐藏域的名字和数据也被包含到GETPOST数据里,我们可以利用这一机制来维持会话信息。然而,这种方法有一个很大的缺点,它要求所有页面都是动态生成的,因为整个问题的核心就是每个会话都要有一个唯一标识符。 

      Servlet为我们提供了一种与众不同的方案:HttpSession APIHttpSession API是一个基于Cookie或者URL改写机制的高级会话状态跟踪接口:如果浏览器支持Cookie,则使用Cookie;如果浏览器不支持Cookie或者Cookie功能被关闭,则自动使用URL改写方法。Servlet开发者无需关心细节问题,也无需直接处理Cookie或附加到URL后面的信息,API自动为Servlet开发者提供一个可以方便地存储会话信息的地方。 


    会话状态跟踪API 

      在Servlet中使用会话信息是相当简单的,主要的操作包括:查看和当前请求关联的会话对象,必要的时候创建新的会话对象,查看与某个会话相关的信息,在会话对象中保存信息,以及会话完成或中止时释放会话对象。 

      1查看当前请求的会话对象 

      查看当前请求的会话对象通过调用HttpServletRequestgetSession方法实现。如果getSession方法返回null,你可以创建一个新的会话对象。但更经常地,我们通过指定参数使得不存在现成的会话时自动创建一个会话对象,即指定getSession的参数为true。因此,访问当前请求会话对象的第一个步骤通常如下所示: 

    HttpSession session = request.getSession(true); 

      2查看和会话有关的信息 

      HttpSession对象生存在服务器上,通过Cookie或者URL这类后台机制自动关联到请求的发送者。会话对象提供一个内建的数据结构,在这个结构中可以保存任意数量的键-值对。查看以前保存的数据使用的是getAttribute ("key")方法。getAttribute返回Object,因此你必须把它转换成更加具体的数据类型。如果参数中指定的键不存在,getAttribute返回null  

      大多数时候我们都是根据特定的名字寻找与它关联的值,但也可以调用getAttributeNames得到所有属性的名字。getAttributeNames返回的是一个Enumeration

     

      虽然开发者最为关心的往往是保存到会话对象的数据,但还有其他一些信息有时也很有用。 

      getID:该方法返回会话的唯一标识。有时该标识被作为键-值对中的键使用,比如会话中只保存一个值时,或保存上一次会话信息时。 

      isNew:如果客户(浏览器)还没有绑定到会话则返回true,通常意味着该会话刚刚创建,而不是引用自客户端的请求。对于早就存在的会话,返回值为false 

      getCreationTime:该方法返回建立会话的以毫秒计的时间,从1970.01.01GMT)算起。要得到用于打印输出的时间值,可以把该值传递给Date构造函数,或者GregorianCalendarsetTimeInMillis方法。 

      getLastAccessedTime:该方法返回客户最后一次发送请求的以毫秒计的时间,从1970.01.01GMT)算起。 

      getMaxInactiveInterval:返回以秒计的最大时间间隔,如果客户请求之间的间隔不超过该值,Servlet引擎将保持会话有效。负数表示会话永远不会超时。 

      3:在会话对象中保存数据 

      如上节所述,读取保存在会话中的信息使用的是getAttribute方法。保存数据使用setAttribute,并指定键和相应的值。注意setAttribute将替换任何已有的值。有时候这正是我们所需要的(如下例中的referringPage),但有时我们却需要提取原来的值并扩充它(如下例previousItems)。示例代码如下: 

    在会话对象中保存数据
            HttpSession session = request.getSession(true); 
            session. setAttribute (
    "referringPage", request.getHeader("Referer")); 
            ShoppingCart previousItems 
    = (ShoppingCart)session. getAttribute ("previousItems"); 
            
    if (previousItems == null) { 
              previousItems 
    = new ShoppingCart(); 
            } 
            String itemID 
    = request.getParameter("itemID"); 
            previousItems.addEntry(Catalog.getEntry(itemID)); 

            session. setAttribute (
    "previousItems", previousItems); 

     

      

     

     实例:显示会话信息 

      下面这个例子生成一个Web页面,并在该页面中显示有关当前会话的信息。 

    ShowSession.java
    package com.test.servlet;

    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.net.*;
    import java.util.*;

    public class ShowSession extends HttpServlet {
        
    public void doGet(HttpServletRequest request, HttpServletResponse response)
                
    throws ServletException, IOException {
            HttpSession session 
    = request.getSession(true);
            response.setContentType(
    "text/html");
            PrintWriter out 
    = response.getWriter();
            String title 
    = "Searching the Web";
            String heading;
            Integer accessCount 
    = new Integer(0);
            ;
            
    if (session.isNew()) {
                heading 
    = "Welcome, Newcomer";
            } 
    else {
                heading 
    = "Welcome Back";
                Integer oldAccessCount 
    =
                (Integer) session.getAttribute(
    "accessCount");
                
    if (oldAccessCount != null) {
                    accessCount 
    = new Integer(oldAccessCount.intValue() + 1);
                }
            }
            session.setAttribute(
    "accessCount", accessCount);

            out.println(ServletUtilities.headWithTitle(title)
                    
    + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">"
                    
    + heading + "</H1>\n"
                    
    + "<H2>Information on Your Session:</H2>\n"
                    
    + "<TABLE BORDER=1 ALIGN=CENTER>\n"
                    
    + "<TR BGCOLOR=\"#FFAD00\">\n" + " <TH>Info Type<TH>Value\n"
                    
    + "<TR>\n" + " <TD>ID\n" + " <TD>" + session.getId() + "\n"
                    
    + "<TR>\n" + " <TD>Creation Time\n" + " <TD>"
                    
    + new Date(session.getCreationTime()) + "\n" + "<TR>\n"
                    
    + " <TD>Time of Last Access\n" + " <TD>"
                    
    + new Date(session.getLastAccessedTime()) + "\n" + "<TR>\n"
                    
    + " <TD>Number of Previous Accesses\n" + " <TD>" + accessCount
                    
    + "\n" + "</TABLE>\n" + "</BODY></HTML>");
        }

        
    public void doPost(HttpServletRequest request, HttpServletResponse response)
                
    throws ServletException, IOException {
            doGet(request, response);
        }
    }
  • 相关阅读:
    设计模式(6)--Adapter(适配器模式)--结构型
    设计模式原则(1)--Single Responsibility Principle(SRP)--单一职责原则
    设计模式(5)--Builder(建造模式)--创建型
    设计模式(4)--AbstractFactory(抽象工厂模式)--创建型
    设计模式(3)--SimpleFactory( [1] 简单工厂模式)--创建型
    JS 的map和array集合组合返回JSON字符串
    HTML中直接写js 函数
    设计模式(3)--FactoryMethod( [2] 工厂方法模式)--创建型
    图片剪贴工具类
    远程Get,Post请求工具类
  • 原文地址:https://www.cnblogs.com/myparamita/p/1498524.html
Copyright © 2011-2022 走看看