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="...">。这意味着,当表单被提交时,隐藏域的名字和数据也被包含到GET或POST数据里,我们可以利用这一机制来维持会话信息。然而,这种方法有一个很大的缺点,它要求所有页面都是动态生成的,因为整个问题的核心就是每个会话都要有一个唯一标识符。
Servlet为我们提供了一种与众不同的方案:HttpSession API。HttpSession API是一个基于Cookie或者URL改写机制的高级会话状态跟踪接口:如果浏览器支持Cookie,则使用Cookie;如果浏览器不支持Cookie或者Cookie功能被关闭,则自动使用URL改写方法。Servlet开发者无需关心细节问题,也无需直接处理Cookie或附加到URL后面的信息,API自动为Servlet开发者提供一个可以方便地存储会话信息的地方。
会话状态跟踪API
在Servlet中使用会话信息是相当简单的,主要的操作包括:查看和当前请求关联的会话对象,必要的时候创建新的会话对象,查看与某个会话相关的信息,在会话对象中保存信息,以及会话完成或中止时释放会话对象。
查看当前请求的会话对象
查看当前请求的会话对象通过调用HttpServletRequest的getSession方法实现。如果getSession方法返回null,你可以创建一个新的会话对象。但更经常地,我们通过指定参数使得不存在现成的会话时自动创建一个会话对象,即指定getSession的参数为true。因此,访问当前请求会话对象的第一个步骤通常如下所示:
HttpSession session = request.getSession(true);
查看和会话有关的信息
HttpSession对象生存在服务器上,通过Cookie或者URL这类后台机制自动关联到请求的发送者。会话对象提供一个内建的数据结构,在这个结构中可以保存任意数量的键-值对。在2.1或者更早版本的Servlet API中,查看以前保存的数据使用的是getValue("key")方法。getValue返回Object,因此你必须把它转换成更加具体的数据类型。如果参数中指定的键不存在,getValue返回null。
API 2.2版推荐用getAttribute来代替getValue,这不仅是因为getAttribute和setAttribute的名字更加匹配(和getValue匹配的是putValue,而不是setValue),同时也因为setAttribute允许使用一个附属的HttpSessionBindingListener 来监视数值,而putValue则不能。
但是,由于目前还只有很少的商业Servlet引擎支持2.2,下面的例子中我们仍旧使用getValue。这是一个很典型的例子,假定ShoppingCart是一个保存已购买商品信息的类:
HttpSession session = request.getSession(true); ShoppingCart previousItems = (ShoppingCart)session.getValue("previousItems"); if (previousItems != null) { doSomethingWith(previousItems); } else { previousItems = new ShoppingCart(...); doSomethingElseWith(previousItems); } |
大多数时候我们都是根据特定的名字寻找与它关联的值,但也可以调用getValueNames得到所有属性的名字。getValuesNames返回的是一个String数组。API 2.2版推荐使用getAttributeNames,这不仅是因为其名字更好,而且因为它返回的是一个Enumeration,和其他方法(比如HttpServletRequest的getHeaders和getParameterNames)更加一致。
虽然开发者最为关心的往往是保存到会话对象的数据,但还有其他一些信息有时也很有用。
getID:该方法返回会话的唯一标识。有时该标识被作为键-值对中的键使用,比如会话中只保存一个值时,或保存上一次会话信息时。
isNew:如果客户(浏览器)还没有绑定到会话则返回true,通常意味着该会话刚刚创建,而不是引用自客户端的请求。对于早就存在的会话,返回值为false。
getCreationTime:该方法返回建立会话的以毫秒计的时间,从1970.01.01(GMT)算起。要得到用于打印输出的时间值,可以把该值传递给Date构造函数,或者GregorianCalendar的setTimeInMillis方法。
getLastAccessedTime:该方法返回客户最后一次发送请求的以毫秒计的时间,从1970.01.01(GMT)算起。
getMaxInactiveInterval:返回以秒计的最大时间间隔,如果客户请求之间的间隔不超过该值,Servlet引擎将保持会话有效。负数表示会话永远不会超时。
在会话对象中保存数据
如上节所述,读取保存在会话中的信息使用的是getValue方法(或,对于2.2版的Servlet规范,使用getAttribute)。保存数据使用putValue(或setAttribute)方法,并指定键和相应的值。注意putValue将替换任何已有的值。有时候这正是我们所需要的(如下例中的referringPage),但有时我们却需要提取原来的值并扩充它(如下例
previousItems)。示例代码如下: HttpSession session = request.getSession(true); session.putValue("referringPage", request.getHeader("Referer")); ShoppingCart previousItems = (ShoppingCart)session.getValue("previousItems"); if (previousItems == null) { previousItems = new ShoppingCart(...); } String itemID = request.getParameter("itemID"); previousItems.addEntry(Catalog.getEntry(itemID));
session.putValue("previousItems", previousItems); |
实例:显示会话信息
下面这个例子生成一个Web页面,并在该页面中显示有关当前会话的信息。
package hall;
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 = // 在Servlet API 2.2中使用getAttribute而不是getValue (Integer)session.getValue("accessCount"); if (oldAccessCount != null) { accessCount = new Integer(oldAccessCount.intValue() + 1); } } // 在Servlet API 2.2中使用putAttribute session.putValue("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); } } |
分享到:
相关推荐
10.1 会话状态概述 HTTP协议的“无状态”(Stateless)特点带来了一系列的问题。特别是通过在线商店购物时,服务器不能顺利地记住以前的事务就成了严重的问题。它使得“购物篮”之类的应用很难实现:当我们把商品...
BFD控制报文是UDP报文,端口号3784,BFD提供异步检测模式,连续3个没有收到BFD控制报文,则认为BFD会话状态down。 三、BFD配置实施 AR2和SW5及SW6配置OSPF并建立邻居关系,详细了解OSPF相关知识可以参考HCIP OSPF...
通过创建BFD会话,可以实现快速检测网络中链路故障。...15 配置BFD会话修改端口状态表 16 配置BFD与接口联动功能 17 配置BFD会话进入AdminDown状态 18 配置静态自协商BFD for TE 19 配置BFD会话认证信息 20 维护BFD
BFD 会话管理包括会话状态、会话迁移过程和会话建立方式。 会话状态: * Down:会话处于 Down 状态或刚刚创建。 * Init:已经能够与对端系统通信,本端希望使会话进入 Up 状态。 * Up:会话已经建立成功。 * ...
Android Telephony 概述分析 Android Telephony 是一个核心组件,负责处理移动设备的电话、短信和SIM卡功能。在Android系统中,它构建了一个复杂的架构,与硬件接口(RIL,Radio Interface Layer)紧密协作,确保...
流级的流量监控会将一次网络会话的数据流聚合起来,只记录会话信息的方式数据量更小,也更加易于理解和管理.状态监控数据是指网络中各种软硬件资源的运行状态信息,如CPU 利用率、网络吞吐率、邮件服务是否正常等等...
【实验内容概述】 本次实验主要涉及了Web应用开发中的会话技术,具体包括Cookie和Session的使用,以及在实际场景中的应用。实验旨在让学生理解如何通过这两种技术来维持用户状态,实现用户数据的持久化存储。 1. *...
FTP服务器 一、FTP服务器概述 FTP客户端 端口21 数据传输终止 会话状态继续维 持 端口1068 端口21 连接建立 端口1068 端口21 维持会话状态 端口1068 FTP服务器端 FTP会话终止 连接断开 端口20 数据传输 端口1045 ...
中期呼叫交易则可以在不改变SIP会话状态的情况下执行,比如在通话中添加或删除参与者。 3. **构建支持业务处理能力的基础结构**:SIP协议的扩展可以创建一个更加灵活的框架,支持各种业务处理,如重叠信令、DTMF...
学习如何在 Shiro 中管理用户会话状态。 掌握会话的创建、维护和销毁。 密码加密: 学习如何使用 Shiro 进行密码的加密和验证。 了解不同的密码加密算法和安全性。 Remember Me 功能: 理解 Remember Me 功能的
Novation诺维逊 Launchpad mini MK1&MK2 用户说明书.pdf ...本文档提供了 Launchpad mini 的使用指南,涵盖了硬件设置、Ableton Live 设置、会话模式、导航会话视图、按钮颜色指示和会话概述等方面的知识点。
6 会话状态:会话管理 7 作为JSP:使用JSP 8 没有脚本的页面:无脚本的JSP 9 强大的定制标记:使用JSTL 10 JSTL也有力不能及的时候:定制标记开发 11 部署Web应用:Web应用部署 12 要保密,要安全:Web应用...
是一个用于监控和管理PowerCenter服务器的图形界面,用户可以在这里配置服务器、管理用户权限、查看日志和监控作业运行状态。 4. **Repository Manager** Repository Manager是用于管理Repository的工具,用户...
6 会话状态:会话管理 7 作为JSP:使用JSP 8 没有脚本的页面:无脚本的JSP 9 强大的定制标记:使用JSTL 10 JSTL也有力不能及的时候:定制标记开发 11 部署Web应用:Web应用部署 12 要保密,要安全:Web应用...
例如,从"state"到"status"的改变,以及加入RFC(Request for Comments)标准,增加了错误处理和会话状态管理。 **内容概览** 规范中包含了术语表、参考资料、概述、目标、最佳实践、客户端、扫描仪、HTTPS安全、...
6 会话状态:会话管理 7 作为JSP:使用JSP 8 没有脚本的页面:无脚本的JSP 9 强大的定制标记:使用JSTL 10 JSTL也有力不能及的时候:定制标记开发 11 部署Web应用:Web应用部署 12 要保密,要安全:Web应用...
而PGA则是为每个用户进程单独分配的内存,存储用户特定的信息,如会话状态、SQL语句解析结果等。 SGA的主要组件包括: 1. 数据高速缓冲区:存储从数据文件中读取的数据,以提高数据访问速度。数据高速缓冲区由脏...
EPC 网络概述 EPC 网络是 LTE(Long-Term Evolution,长期演进)网络的一个重要组成部分,负责处理用户的移动性管理、承载管理、鉴权认证等功能。EPC 网络主要由多个网元组成,包括 HSS、MME、SGW、PGW、e-NodeB、...
4. ORA-00021, 22, 23: 这些错误与会话状态和权限有关,可能是因为会话已关联到其他进程,ID无效,或者尝试分离会话时出现问题。解决方法可能包括重新启动会话或调整会话设置。 5. ORA-00024, 25, 26: 这些错误涉及...
2.2.3 状态检测技术和会话表 2.3 ASPF技术原理 3.0 NAT技术 3.1 NAT概述 3.2.1 源NAT 3.2.2 目的NAT 3.2.3 双向NAT 3.2.4 NAT Server 3.3 NAT ALG 4.1 双机热备概述 4.2.1 VRRP 4.2.2 VGMP 4.2.3 HRP 4.2.4 心跳线 ...