简介
应用程序状态的有效管理是设计分发式应用程序的一个重要方面。 本指南概述了 J2EE 应用程序中一些常见设计注意事项和状态管理机制。
应在项目的“精化”阶段阐明与状态管理相关的设计注意事项。软件设计人员应将常规状态管理方法作为与“分析与设计规程”活动:定义候选体系结构相关联活动的一部分进行检验。在 任务:体系结构分析过程中,软件设计人员应检验应用程序的可伸缩性和性能需求,以确定为使应用程序能够满足性能目标而需要使用的状态管理技术。由于在“精化”阶段优化了应用程序的设计,所以设计人员需要定义特定于
J2EE 的设计和实施机制,以管理任务:确定设计机制中应用程序的状态信息。
如概念:J2EE 部署配置中所述,J2EE
应用程序可由几个逻辑层组成,这些逻辑层分布在一个到多个物理层(机器)上。在对状态管理做出简短的技术概述之后,本指南的剩余部分将讨论可在多个应用程序层中使用的各种状态管理设计和实施机制。
请注意,软件设计人员应记录已选作工作产品:软件体系结构文档一部分的机制,并应当提供关于使用这些机制的指南,这些指南将作为特定于项目的设计指南的一部分。
技术概述
有一种增长的趋势,即构建以某一形式与 Internet 交互的分发式应用程序。即使 Internet 的基础在本质上是无状态的,也时常有必要管理状态以构建任何种类的业务应用程序。考虑某个 Internet
应用程序,其中某一用户单击某个链接从页面 A 转至页面 B。处理对页面 B 的请求的应用程序不再有权访问用于处理页面 A 的信息。静态 Web 页面可能会接受该行为,但大多数业务应用程序需要关于上次处理的某些信息。 在这种情况下可使用
J2EE 提供的状态管理机制。
临时状态与持久状态
在深入研究状态管理指南之前,区分不同类型的状态信息是很重要的。状态信息大致可分为两类:临时状态(仅在应用程序活动时存在)和持久状态(在应用程序终止之后存在)。
临时状态信息的生存期与包含该信息的实体的活动期相同。例如,在普通 Java 类中作为字段存储的状态信息。如果包含该类的容器由于任何原因而终止,除非已经在别处复制了数据(例如在备份服务器上),否则将丢失状态信息。
持久状态信息的生存期与用于维护状态信息的数据存储的生存期同样长。持久状态信息通常存储在文件中或数据库中,并在应用程序需要时装入。对持久状态信息做出的任何更改都必须写回到数据库中。持久数据存储的完整性和可恢复性应与应用程序正在访问的数据保持一致。
持久状态的一个示例是存储在数据存储器(例如关系数据库)中的信息。
会话状态
Web 客户机通常要求能够提出多个浏览器请求,以在保留特定于客户机的信息(例如购物车中的商品)的同时浏览页面。Web 应用程序处理这种情况的方式是:创建会话标识并将状态数据与该会话标识相关联。会话标识及关联的状态被称为会话状态。
会话状态是与特定客户机和 Web 应用程序短时间(以分钟或小时计,不以天计)的交互相关联的数据。因此,会话状态是短期数据,一般在某段超时期过后删除,以避免耗费资源。
如稍后部分中所述,可在客户机或服务器上存储会话状态。J2EE 平台提供了特别为管理会话状态而定制的机制,这是因为会话状态在基于 Web 的应用程序中的重要性。
基本持久性机制
以下是 Web 应用程序用于存储状态的常见机制。
Cookie
Cookie 是存储在基于 Web 的客户机上的小文本文件。服务器可在客户机上存储 cookie。后续的客户机请求将 cookie 发送到服务器,使服务器可访问存储在 cookie 中的状态数据。
使用 cookie 时的一些问题为:
-
许多用户认为 cookie 将危及安全和/或隐私,因此他们禁用了 cookie。
-
Cookie 头具有大小限制,这将限制可存储的数据量。
-
某些协议,例如无线访问协议(WAP)不支持 cookie。
-
如果客户机从其他位置(例如其他机器)登录,在该位置存储的 cookie 则不可用。
-
状态数据必须由字符串值表示。
URL 重写
URL 重写是将会话状态嵌入到每个页面所引用的 URL 中的一种机制。当 Web 服务器生成要传递给客户机的页面时,它会将会话状态编入页面的 URL 代码中。然后,当用户单击 URL 时,存储在 URL
中的状态数据就发回到服务器,从而允许服务器重建会话环境。类似的机制使用 HTML 隐藏字段。使用这些机制时的问题有:
-
给定会话中的所有页面都必须由服务器处理,否则服务器可能无法跟踪会话。
-
当客户端关闭浏览器或通过输入或使用书签链接特定的 URL 时,状态将不存在。
-
与 cookie 相同,当客户机从其他位置登录时,将无法使用状态数据。
-
与 cookie 相同,状态数据必须由字符串值表示。
平面文件
平面文件是维护持久状态信息的最简单方法之一。一经初始化,即可读取平面文件以确定初始状态值。每当状态发生更改时,都必须重写文件以保持状态。在平面文件中维护应用程序状态的某些缺点为:
-
由于应用程序必须锁定应用程序对象,以防止在更新应用程序状态变量并将这些变量重写到平面文件时访问全局数据,所以这将对应用程序的可伸缩性造成负面影响。
-
在大多数情况下,更新数据将需要重写整个文件。
-
平面文件并不总是在出错时提供可恢复性。
XML
在 XML 文件中保存持久状态信息是对平面文件的一个提高。与平面文件相比,在 XML 文件中保存应用程序状态的某些优点为:
-
XML 文件提供了平面文件中不存在的结构。
-
XMl 文件可以使用标准 API 进行语法分析。
-
XML 文件通常可移植性更高。
数据库
在数据库中保存持久状态信息将提供最大的可恢复性。在数据库中保存应用程序状态的某些优点为:
-
表格设计将提供结构。
-
当应用程序变量更新时,无需重写整个应用程序状态。仅需重写更新的信息。
-
可通过协调应用程序状态恢复和生产数据库恢复来维持一致性。
-
在极为可靠的情况下,可将数据库服务器分群。
可使用 Java 数据库连接(JDBC)API 来访问数据库。JDBC 还可用于访问其他的表列数据源,包括电子表格和平面文件。
特定于 J2EE 的机制
J2EE 平台提供了用于管理状态的特定机制。这些高级机制可配置为使用目前所述的一个或多个基本机制。
Servlet 环境
Servlet 可使用 servlet 环境来保存适用于多个客户机和客户机会话的数据。
存储在 servlet 环境中的数据在本质上是 J2EE 应用程序的全局变量。因此,使用应用程序状态会对应用程序设计产生巨大的影响。软件设计人员需要在任务:确定设计机制过程中考虑以下因素,以确定 servlet 环境是否合适:
-
Servlet 环境可在单个进程中维护,从而不会在多个服务器(群集)之间共享。如果这不符合应用程序的可伸缩性需要,设计人员则需要考虑将状态存储为会话状态。
-
Servlet 环境是进程内存的一部分,因此通常在进程终止后不再受到维护。
-
多个线程可访问全局数据。全局数据的锁定和同步可能影响应用程序的可伸缩性。
HTTP 会话对象
Servlet 和 JSP 可在 HTTP 会话对象中存储与特定客户机会话相关联的数据。如果在会话对象中存储数据,则可能存在关于如何在多个服务器之间提供会话数据的问题。
有些供应商能将客户机请求传递给同一服务器,这种做法称为“服务器亲缘关系”。
在处理客户机请求的过程中可使用 HTTP 会话对象,但是它可能会或不会存储在众多请求之间的服务器上。服务器可能是可配置的,以使用前述的任一基本持久性机制,包括在客户机的 cookie
中或是在服务器的文件或数据库中存储会话状态。它还可使用户能够在服务器间复制内存中的会话数据。
选择机制的方式为,通过配置服务器(JSP 和 servlet 是独立于所选机制进行编码的),使用 Servlet 规范指定的 API 来访问会话对象。
Enterprise JavaBeans
Enterprise JavaBeans 包括用于存储状态的高级机制,这些机制是以前述较低级机制(例如数据库和文件)为基础的。有状态会话 Bean 用于存储与特定客户机会话相关联的数据,而实体 Bean 则用于存储长期数据。关于 EJB
存储的状态的讨论,请参阅指南:Enterprise JavaBean(EJB)。
设计会话状态
Web 客户机通常要求能够提出多个浏览器请求,以在保留特定于客户机的信息(例如购物车中的商品)的同时浏览页面。Web 应用程序处理这种情况的方式是:创建会话标识并将状态数据与该会话标识相关联。
会话标识本身是通过一到两种机制存储在客户机上的:
-
cookie - 客户机浏览器根据每个请求将该 cookie 发送到服务器,这使得服务器能够重新确立会话状态。
-
URL 重写 - 由服务器传递给客户机的页面中 URL 已对会话标识进行编码。用户单击这样的 URL 时,会话标识就发送到服务器,允许服务器重新确定会话状态。
服务器被配置为使用所选的方法。应对 Servlet 和 JSP 进行编码,以在不考虑所配置方法的情况下运作。特别地,使用 HttpServletResponse.encodeURL() 方法对所有 URL 进行编码。该方法将检查是否启用
URL 重写,如果已启用,则执行编码。
与会话标识相关的数据可存储在 HTTP 会话对象中(在此,JSP 和 servlet 可访问这些数据),或存储在会话 Bean 中。
会话标识和相关的数据均应设置为超时,这样,长时间未使用的会话数据就不会无限期地消耗资源。设计人员应选择适当的超时期。
选择正确的机制
出于简单和性能方面的原因,设计人员应考虑在客户机中存储会话状态。当在客户机上管理和存储状态时,服务器就不必消耗资源来存储状态信息或确保其一致性。在客户机上存储状态信息的不利之处在于:一有必要,就需要随时将信息发送给服务器,这将引起网络延时的相关问题。如果您有不希望客户机看到的会话状态数据,则可能还有安全性的注意事项。在这种情况下,可选择加密。
如果您的应用程序具有大量会话状态,一般来说,将该状态存储在服务器(通常服务器的大小和类型限制较少)上更为可取。
通常应将演示问题的相关会话状态存储在 HTTP 会话对象中,而有状态会话 Bean 应包含正确实施业务逻辑所需的状态。应避免状态数据的重复 - 反过来,将任何重复的状态数据移到 HTTP 会话中,并根据需要将这些数据作为会话 Bean
方法调用的参数传递到会话 Bean 中。
如果服务器节点发生故障后存储在服务器上的会话数据必须保留下来,则考虑使用某一机制来维持或复制会话数据。
设计更长久的状态
会话数据代表着超时的短期客户机数据。可能还需要生存期长得多的数据。
用于这类数据的适当机制取决于所存储数据的本质。可选择 Cookie、平面文件、XML 文件和数据库。对数据库访问而言,实体 Bean 通常是最好的选择。关于详细信息,请参阅指南:实体 Bean。
|