当前位置: 代码迷 >> Web前端 >> 应用会话和会话持久性 Weblogic session
  详细解决方案

应用会话和会话持久性 Weblogic session

热度:827   发布时间:2012-11-18 10:51:21.0
使用会话和会话持久性 Weblogic session

?

Jump to Content Downloads ?|? Product Documentation ?|? Support
BEA Systems homepage
dev2dev Home????? Dev?Centers????? Newsgroups????? Community????? CodeShare?????

开发 WebLogic Server 的 Web 应用程序、Servlet 和 JSP

???? 上一页 ? 下一页 ? ? 在新窗口中打开目录 ? ? ?

在此处开始内容

使用会话和会话持久性

以下部分描述如何设置和使用会话以及会话持久性:

  • HTTP 会话概述
  • 设置会话管理
  • 配置会话持久性
  • 用 URL 重写替换 Cookie
  • Servlet 会话跟踪

?


HTTP 会话概述

通过会话跟踪,您可以跟踪用户在多个自身无状态的 servlet 或 HTML 页面上的进度。会话被定义为特定时间段内来自同一个客户端的一系列相关的浏览器请求。会话跟踪将一系列浏览器请求联结起来(可以将这些请求当作页面来考虑),这些请求整体上可能具有一定的含义,例如购物车应用程序。

?


设置会话管理

默认情况下,WebLogic Server 设置为可以处理会话跟踪。无需设置以下任何属性即可使用会话跟踪。但是,配置 WebLogic Server 管理会话的方式是调整应用程序以获得最佳性能的关键部分。设置会话管理时,您需确定如下因素:

  • 预期访问 servlet 的用户的数量
  • 每个会话的持续时间
  • 每个用户的预期数据存储量
  • 向 WebLogic Server 实例分配的堆大小

您还可以永久存储来自 HTTP 会话的数据。请参阅配置会话持久性 。

HTTP 会话属性

通过在 WebLogic 特定的部署描述符 weblogic.xml 中定义各种属性,您可以配置 WebLogic Server 会话跟踪。有关会话特性的完整列表,请参阅 session-descriptor

在以前的 WebLogic Server 版本中,引入了对 SessionID 格式的一个更改,以致某些负载平衡器丧失了保持会话粘滞性的能力。服务器启动标志 -Dweblogic.servlet.useExtendedSessionFormat=true 保留了负载均衡应用程序保持会话粘滞性所需要的信息。如果激活了 URL 重写功能,且启动标志设置为真,则扩展会话 ID 格式将属于 URL 的一部分。

会话超时

您可以指定 HTTP 会话过期的时间间隔。会话过期时,将放弃会话中存储的所有数据。可以在 web.xml 或 weblogic.xml 中设置时间间隔:

  • 在 WebLogic 特定的部署描述符 weblogic.xml 中的 session-descriptor 元素中设置 timeout-secs 参数值。该值以秒为单位进行设置。有关详细信息,请参阅 session-descriptor
  • 在 J2EE 标准 Web 应用程序部署描述符 web.xml 中设置 session-timeout 元素。

配置 WebLogic Server 会话 Cookie

客户端浏览器支持 cookie 时,WebLogic Server 使用 cookie 进行会话管理。

默认情况下,WebLogic Server 用于跟踪会话的 cookie 设置为暂态,其生存期不会超过会话期间。用户退出浏览器时,cookie 丢失,会话结束。此行为主要用于会话,建议您以此方式使用会话。

您可以在 WebLogic 特定部署描述符 weblogic.xml 中配置 cookie 的 session-tracking 参数。会话及 cookie 相关参数的完整列表位于 session-descriptor 中。

配置生存期超过会话期间的应用程序 Cookie

要获得生存期更长的客户端用户数据,您可以编写自己的应用程序,通过 HTTP servlet API 在浏览器上创建和设置自己的 cookie。应用程序不应试图使用与 HTTP 会话关联的 cookie。您的应用程序可能会使用 cookie 以使用户从特定计算机自动登录,这样,您需要设置新的 cookie 以持续更长时间。请记住,只能从此特定客户端计算机发送 cookie。如果用户必须从多个位置进行访问,您的应用程序应该在服务器上存储数据。

您不能直接将浏览器 cookie 的期限与会话时间长度关联起来。否则,如果 cookie 在其关联会话之前过期,则会话会变得孤立。而如果会话在其关联 cookie 之前过期,则 servlet 无法找到该会话。这种情况下,当调用 request.getSession(true) 方法时,将自动分配一个新会话。

可以使用 weblogic.xml 部署描述符的会话描述符中的 cookie-max-age-secs 元素设置 cookie 的最大生命周期。请参阅 cookie-max-age-secs 。

退出和结束会话

用户身份验证信息既存储于用户会话数据中,也存储于 Web 应用程序所定位的服务器或虚拟主机的上下文中。通常用于使用户退出的 session.invalidate() 方法仅使用户的当前会话失效,用户身份验证信息仍有效,且存储于服务器或虚拟主机的上下文中。而如果服务器或虚拟主机仅承载一个 Web 应用程序,则 session.invalidate() 方法实际上会使用户退出。

针对多个 Web 应用程序使用身份验证时,有多种 Java 方法和策略可以使用。有关详细信息,请参阅退出和结束会话 。

使 Web 应用程序共享同一个会话

默认情况下,Web 应用程序不共享同一个会话。如果您希望 Web 应用程序共享同一个会话,您可以在 weblogic-application.xml 部署描述符中配置应用程序级别上的会话描述符。要使 Web 应用程序共享同一个会话,请将 weblogic-application.xml 部署描述符中会话描述符中的 sharing-enabled 特性设置为 true 。请参阅 session-descriptor 中的“sharing-enabled”。

应用程序级别上指定的会话描述符配置将替代在 Web 应用程序级别上为应用程序中所有 Web 应用程序指定的任何会话部署描述符配置。如果您在 Web 应用程序级别上将 sharing-enabled 特性设置为真,则将忽略该设置。

如果您在 weblogic-application.xml 部署描述符中指定会话描述符,并将 sharing-enabled 特性设置为 true ,则应用程序中的所有 Web 应用程序将自动使用同一个会话实例启动,如以下示例所示:

<?xml version="1.0" encoding="ISO-8859-1"?>

<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90";;>
   ...
<session-descriptor>	
     <persistent-store-type>memory</persistent-store-type>
     <sharing-enabled>true</sharing-enabled>
     ...
</session-descriptor>
...
</weblogic-application>

?


配置会话持久性

使用会话持久性永久存储 HTTP 会话对象中的数据,以便支持 WebLogic Server 群集之间的故障转移和负载平衡,应用程序存储 HTTP 会话对象中的数据时,数据必须是可序列化的。

会话持久性有五种不同的实现方法:

  • 内存(单个服务器,非复制)
  • 文件系统持久性
  • JDBC 持久性
  • 基于 Cookie 的会话持久性
  • 内存中复制(跨群集)

此处仅讨论前四项;内存中复制将在使用 WebLogic Server 群集 中的 HTTP 会话状态复制 中讨论。

基于文件、JDBC 和 cookie 的会话持久性与内存(单服务器,非填充)会话持久性具有某些共同的属性。每个持久性方法具有其自己的一组可配置参数,如以下部分所讨论。这些参数是 weblogic.xml 部署描述符文件中 session-descriptor 元素的子元素。

不同类型的会话持久性的共有特性

此部分描述基于文件的持久性和基于 JDBC 的持久性共用的参数。通过在 weblogic.xml 部署描述符文件中的 session-descriptor 元素中定义下列参数,您可以配置内存中保留的会话数量。以下参数仅适用于您使用会话持久性时:

cache-size

限制内存中一次可存在的活动缓存会话数目。如果您期望使用大量的同时处于活动状态的会话,则您会希望这些会话不要耗尽服务器的内存,否则会因反复与虚拟内 存之间进行交换而导致性能问题。当缓存满时,最近不常使用的会话将存储于永久性存储中,需要时会自动重新调用它们。如果不使用持久性,将忽略此属性,且对 主内存中允许的会话数量没有任何软限制。默认情况下,缓存中的会话数量是 1028。要关闭缓存,请将此值设置为 0。请参阅 cache-size 。
注意: 基于 JDBC 和基于文件的会话使用 cache-size 的目的仅仅是维护内存中出现的缓存。它不适用于其他持久性类型。

invalidation-interval-secs

设置 WebLogic Server 在执行超时会话和无效会话的清理检查与删除旧会话并释放内存之间需要等待的时间(秒)。使用此元素调整 WebLogic Server 以在高流量站点上获得最佳性能。请参阅 invalidation-interval-secs 。
最小值是每秒 1 次(1)。最大值是每周一次(604,800 秒)。如果没有设置,则特性默认为 60 秒。

使用基于内存的单服务器非复制持久性存储

使用基于内存的存储时,所有会话信息都存储在内存中,当您停止并重新启动 WebLogic Server 时,这些信息都会丢失。要使用基于内存的单服务器非复制持久性存储,请将 weblogic.xml 部署描述符文件中的 session-descriptor 元素中 persistent-store-type 参数设置为 memory。请参阅 persistent-store-type 。

注意: 如果运行 WebLogic Server 时没有分配足够的堆大小,服务器将由于高额负载而导致内存不足。

使用基于文件的持久性存储

要为会话配置基于文件的持久性存储,请执行下列操作:

  1. 在部署描述符文件 weblogic.xml 中,将 weblogic.xml 部署描述符文件中 session-descriptor 元素中的 persistent-store-type 参数设置为 file 。请参阅 persistent-store-type 。
  2. 设置 WebLogic Server 存储会话的目录。请参阅 persistent-store-dir 。
  3. 注意: 必须自行创建此目录,并确保已为该目录分配适当的访问权限。

使用数据库进行持久性 存储(JDBC 持久性)

JDBC 持久性通过使用专为此目的而提供的 Schema 将会话数据存储在数据库表中。可以使用您有 JDBC 驱动程序的任何数据库。通过使用连接缓冲池配置数据库访问。

由于 WebLogic Server 在使用 JDBC 会话持久性时会使用系统时间确定会话生命周期,所以您必须确保其上服务器是在同一个群集中运行的所有计算机上的系统时钟。

配置基于 JDBC 的持久性存储

要为会话配置基于 JDBC 的持久性存储,请执行下列步骤:

  1. 将 weblogic.xml 部署描述符文件中 session-descriptor 元素中的 persistent-store-type 参数设置为 jdbc 。请参阅 persistent-store-type 。
  2. 使用 weblogic.xml 部署描述符文件中 session-descriptor 元素中的 persistent-store-pool 参数设置要用于持久性存储的 JDBC 连接缓冲池。使用 WebLogic Server 管理控制台中定义的连接缓冲池的名称。请参阅 persistent-store-pool 。
  3. 为基于 JDBC 的持久性设置一个名为 wl_servlet_sessions 的数据库表。连接数据库的连接缓冲池需要具有该表的读/写访问权。
  4. 注意: 如果数据库没有自动创建索引,请在 wl_idwl_context_path 上创建。某些数据库会自动为主关键字创建索引。

    按如下说明设置列名称和数据类型。

    表 8-1 创建 wl_servlet_sessions
    列名
    数据类型
    wl_id
    变量宽度字母数字列,最多 100 位字符;例如 Oracle VARCHAR2(100) .
    主关键字必须按如下设置:
    wl_id + wl_context_path.
    wl_context_path
    变量宽度字母数字列,最多 100 位字符;例如 Oracle VARCHAR2(100)此列用作主关键字的一部分。(请参阅 wl_id 列描述。)
    wl_is_new
    单字符列,例如 Oracle CHAR(1)
    wl_create_time
    数值列,20 位,例如 Oracle NUMBER(20)
    wl_is_valid
    单字符列,例如 Oracle CHAR(1)
    wl_session_values
    大型二进制列;例如 Oracle LONG RAW
    wl_access_time
    数值列,20 位;例如 NUMBER(20)
    wl_max_inactive_interval
    整数列;例如 Oracle Integer 。如果两个客户端请求之间的时间超过此秒数,则会话将失效。负时间值表明会话永不超时。

如果您使用的是 Oracle DBMS,请使用下面的 SQL 语句创建 wl_servlet_sessions 表。请修改该 SQL 语句以用于您的 DBMS。

清单?8-1 使用 Oracle DBMS 创建 wl_servlet_sessions 表

create table wl_servlet_sessions
  ( wl_id VARCHAR2(100) NOT NULL,
    wl_context_path VARCHAR2(100) NOT NULL,
    wl_is_new CHAR(1),
    wl_create_time NUMBER(20),
    wl_is_valid CHAR(1),
    wl_session_values LONG RAW,
    wl_access_time NUMBER(20),
    wl_max_inactive_interval INTEGER,
   PRIMARY KEY (wl_id, wl_context_path) ); 

注意: 您可以使用 jdbc-connection-timeout-secs 参数配置 JDBC 会话持久性等待连接缓冲池中的 JDBC 连接的最大持续时间,超过该时间将无法加载会话数据。有关详细信息,请参阅 jdbc-connection-timeout-secs 。

如果您使用的是 SqlServer2000,请使用下面的 SQL 语句创建 wl_servlet_sessions 表。请修改该 SQL 语句以用于您的 DBMS。

清单?8-2 使用 SqlServer 2000 创建 wl_servlet_sessions 表

create table wl_servlet_sessions
  ( wl_id VARCHAR2(100) NOT NULL,
    wl_context_path VARCHAR2(100) NOT NULL,
    wl_is_new VARCHAR(1),
    wl_create_time DECIMAL,
    wl_is_valid VARCHAR(1),
    wl_session_values IMAGE,
    wl_access_time DECIMAL,
    wl_max_inactive_interval INTEGER,
   PRIMARY KEY (wl_id, wl_context_path) ); 

如果您使用的是 Pointbase,Pointbase 会转换该 SQL。例如,Pointbase 会按照如下方式转换清单?8-1 中提供的 SQL。

清单?8-3 使用 Pointbase SQL 转换创建 wl_servlet_sessions 表

SQL> describe wl_servlet_sessions;

WL_SERVLET_SESSIONS

WL_ID VARCHAR(100) NULLABLE: NO

WL_CONTEXT_PATH VARCHAR(100) NULLABLE: NO

WL_IS_NEW CHARACTER(1) NULLABLE: YES

WL_CREATE_TIME DECIMAL(20) NULLABLE: YES

WL_IS_VALID CHARACTER(1) NULLABLE: YES

WL_SESSION_VALUES BLOB(65535) NULLABLE: YES

WL_ACCESS_TIME DECIMAL(20) NULLABLE: YES

WL_MAX_INACTIVE_INTERVAL INTEGER(10) NULLABLE: YES

Primary Key: WL_CONTEXT_PATH

Primary Key: WL_ID

如果您使用的是 DB2,请使用下面的 SQL 语句创建 wl_servlet_sessions 表。请修改该 SQL 语句以用于您的 DBMS。

清单 8-4 使用 DB2 创建 wl_servlet_sessions 表

CREATE TABLE WL_SERVLET_SESSIONS
(
   WL_ID VARCHAR(100) not null,
   WL_CONTEXT_PATH VARCHAR(100) not null,
   WL_IS_NEW SMALLINT,
   WL_CREATE_TIME DECIMAL(16),
   WL_IS_VALID SMALLINT,
   wl_session_values BLOB(10M) NOT LOGGED,
   WL_ACCESS_TIME DECIMAL(16),
   WL_MAX_INACTIVE_INTERVAL INTEGER,
   PRIMARY KEY (WL_ID,WL_CONTEXT_PATH)

);

如果您使用的是 Sybase,请使用下面的 SQL 语句创建 wl_servlet_sessions 表。请修改该 SQL 语句以用于您的 DBMS。

清单 8-5 使用 Sybase 创建 wl_servlet_sessions 表

create table WL_SERVLET_SESSIONS (
WL_ID                         varchar(100)                   not null  ,
WL_CONTEXT_PATH               varchar(100)                   not null  ,
WL_IS_NEW                     smallint                           null  ,
WL_CREATE_TIME                decimal(16,0)                      null  ,
WL_IS_VALID                   smallint                           null  ,
WL_SESSION_VALUES             image                              null  ,
WL_ACCESS_TIME                decimal(16,0)                      null  ,
WL_MAX_INACTIVE_INTERVAL      int                                null  ,
)
go

alter table WL_SERVLET_SESSIONS
add PRIMARY KEY CLUSTERED (WL_ID, WL_CONTEXT_PATH)
go

JDBC 会话持久性的缓存与数据库更新

如果请求是只读的,WebLogic Server 不会向磁盘中写入 HTTP 会话状态,这表明该请求不修改 HTTP 会话。如果访问该会话,则仅更新数据库中的 wl_access_time 列。

对于非只读请求,每次 HTTP 请求后,Web 应用程序容器都会在数据库中更新会话状态的变化。因此,群集中的任意服务器均可处理一旦发生故障转移时的请求,并从数据库中检索最新会话状态。

为防止多个数据库查询,WebLogic Server 将缓存最近使用的会话。每次请求时,并不从数据库中刷新最近使用的会话。缓存中会话的数量由 WebLogic Server 特定的部署描述符 weblogic.xml 中的 cache-size 参数控制。请参阅 cache-size 。

使用基于 Cookie 的会话持久性

基于 Cookie 的会话持久性提供了会话持久性的无状态解决方案,方法是将所有会话数据存储在用户浏览器的 cookie 中。不需要在会话中存储大量数据时,基于 Cookie 的会话持久性最适用。由于不需要群集故障转移逻辑,所以基于 Cookie 的会话持久性能够简化 WebLogic Server 安装的管理。由于会话存储于浏览器中,而不存储于服务器上,所以启动和停止 WebLogic Server 时不会丢失会话。

基于 cookie 的会话持久性具有某些限制:

  • 只能存储会话中的字符串特性。如果您存储会话中的任何其他类型的对象,则会引发 IllegalArgument 异常。
  • 不能刷新 HTTP 响应(因为必须先将 cookie 写入头数据中,然后才可以提交响应 )。
  • 如果响应内容的长度超出缓冲大小,则自动刷新响应,不更新 cookie 中的会话数据。(缓冲大小默认为 8192 字节。)您可以使用 javax.servlet.ServletResponse.setBufferSize() 方法更改缓冲区大小。
  • 只能使用基本(基于浏览器)身份验证。
  • 会话数据以明文方式发送至浏览器。
  • 必须对用户浏览器进行配置以接受 cookie。
  • 使用基于 cookie 的会话持久性时,字符串内不能使用逗号,否则会引发异常。

要设置基于 cookie 的会话持久性,请执行下列步骤:

  1. 将 weblogic.xml 部署描述符文件中 session-descriptor 元素中的 persistent-store-type 参数设置为 cookie 。请参阅 persistent-store-type 。
  2. 或者,使用 persistent-store-cookie-name 元素为 cookie 设置一个名称。默认值为 WLCOOKIE 。请参阅 persistent-store-cookie-name 。

?


用 URL 重写 替换 Cookie

在某些情况下,浏览器或无线设备可能不接受 cookie,因此无法使用 cookie 进行会话跟踪。对于这种情况,URL 重写是一个解决方案,当 WebLogic Server 检测到浏览器不接受 cookie 时,会自动替换为 URL 重写。URL 重写包括将会话 ID 编码到 servlet 传回浏览器的那些网页的超链接中。当用户随后单击这些链接时,WebLogic Server 将从 URL 地址中提取 ID,并在 servlet 调用 getSession() 方法时查找相应的 HttpSession

在 WebLogic 特定的部署描述符 weblogic.xml 中的 session-descriptor 元素下,设置 url-rewriting-enabled 参数,从而启用 WebLogic Server 中的 URL 重写。此特性的默认值是 true 。请参阅 url-rewriting-enabled 。

URL 重写的编码准则

下面是支持 URL 重写的一般准则。

  • 避免直接向输出流中写入 URL,如下显示:
  • out.println("<a href=\"/myshop/catalog.jsp\">catalog</a>");

    而要使用 HttpServletResponse.encodeURL() 方法,例如:

    out.println("<a href=\"
         + response.encodeURL("myshop/catalog.jsp") 
         + "\">catalog</a>");

    调用 encodeURL() 方法可以确定 URL 是否需要重写。如果确实需要重写,WebLogic Server 将重写 URL,即,在会话 ID 前添加一个分号,然后将其追加到 URL 后面。

  • 除作为 WebLogic Server 响应而返回的 URL 外,还会对发送重定向的 URL 进行编码。例如:
  • if (session.isNew())
    ??response.sendRedirect (response.encodeRedirectUrl(welcomeURL));  

    新建会话时,即使浏览器确实接受 cookie,WebLogic Server 也将使用 URL 重写,因为在初次访问会话时,服务器无法判断浏览器是否接受 cookie。

    当使用插件(Apache、NSAPI、ISAPI、HttpClusterServletHttpProxyServlet )时,如果在使用 response.sendRedirect(url)response.encodeRedirectURL(url) 的后端服务器上使用 URL 重写,则在以下条件下 PathTrimPathPrepend 参数将被应用于该 URL:如果 PathPrepend 为空或已经应用了 PathPrepend ,那么只将 PathTrim 应用于 URL。

  • 通过检查从 HttpServletRequest.isRequestedSessionIdFromCookie() 方法返回的 Boolean,servlet 可以判断给定的会话 ID 是否是从 cookie 中收到的。您的应用程序可能会相应响应,或仅依赖于 WebLogic Server 的 URL 重写。

注意: CISCO 本地定向器负载均衡器要求 URL 重写中使用问号“?”分隔符。由于 WLS URL 重写机制使用分号“;”作为分隔符,因此 URL 重写与该负载均衡器不兼容。

URL 重写和无线访问协议 (WAP)

如果您正在编写 WAP 应用程序,您必须使用 URL 重写,因为 WAP 协议不支持 cookie。另外,某些 WAP 设备对 URL 长度有 128 位字符的限制(其中包括特性),这限制了使用 URL 重写可以传输的数据量。为了给各个特性预留较多空间,可以限制 WebLogic Server 随机生成的会话 ID 的大小。

特别是,如果要使用 WAPEnabled 特性,请通过单击“服务器”箭头符号 “协议”箭头符号 HTTP箭头符号 “高级选项”使用管理控制台。WAPEnabled 特性将会话 ID 的大小限制在 52 位字符内,且不允许使用特殊字符,例如“!”和“#”。还可以使用 weblogic.xml 的 IDLength 参数进一步限制会话 ID 的大小。有关其他详细信息,请参阅 id-length 。

?


Servlet 会话跟踪

通过会话跟踪,可以跟踪用户在多个自身无状态的 servlet 或 HTML 页面上的进度。 会话被定义为特定时间段内来自同一个客户端的一系列相关的浏览器请求。会话跟踪将一系列浏览器请求联结起来(可以将这些请求当作页面来考虑),这些请求整体上可能具有一定的含义,例如购物车应用程序。

以下部分讨论 HTTP servlet 会话跟踪的各个方面:

  • 会话跟踪的历史
  • 通过 HttpSession 对象跟踪会话
  • 会话生命周期
  • 会话跟踪的工作方式
  • 检测会话的开始
  • 设置和获取会话名/值特性
  • 退出和结束会话
  • 配置会话跟踪
  • 用 URL 重写替换 Cookie
  • URL 重写和无线访问协议 (WAP)
  • 使会话持久

会话跟踪的历史

在会话跟踪这个概念成熟之前,开发人员尝试将状态构建在页面中,他们将信息填充在页面的隐藏字段中,或使用一长串追加字符将用户选项嵌入链接中使用的 URL 中。在大多数搜索引擎站点上,您可以看到很好的这样的示例,它们多数仍依赖于 CGI。这些站点通过在 URL 中 HTTP 保留字符 ? 后追加 URL 参数 name =value 对来跟踪用户选项。这种方法会产生非常长的 URL,CGI 脚本必须仔细地对其进行解析和管理。这种方法的问题在于,无法在会话之间传递这些信息。一旦失去对 URL 的控制,即一旦用户离开某个页面,用户信息将永久丢失。

后来,Netscape 引入了浏览器 cookie, 因此您能够为每个服务器存储关于客户端的用户相关信息。但是,某些浏览器仍无法完全支持 cookie,而且某些用户喜欢关闭浏览器中的 cookie 选项。另外一个需要考虑的因素是,多数浏览器限制了 cookie 中可存储的数据量。

与 CGI 方法不同,HTTP servlet 规范定义了一个解决方案,除在服务器上存储单个会话外,还允许服务器存储用户详细信息,避免了由代码处理会话跟踪的复杂性。servlet 可以使用 HttpSession 对象跟踪用户在单个会话期间的输入,并在多个 servlet 之间共享会话详细信息。使用 WebLogic 服务提供的多种方法,可以持久保存会话数据。

通过 HttpSession 对象跟踪会话

根据 WebLogic Server 实现并支持的 Java Servlet API,每个 servlet 都可以使用其 HttpSession 对象访问服务器端会话。通过使用 HttpServletRequest 对象及 request 变量,您可以在 servlet 的 service() 方法中访问 HttpSession 对象,如下所示:

HttpSession session = request.getSession(true);

当使用参数 true 调用 request.getSession(true) 方法时,如果该客户端尚不存在 HttpSession 对象,则将创建该对象。在会话生命周期内,会话对象生存于 WebLogic Server 上,并且会累计与该客户端相关的信息。servlet 会按照需要在会话对象中添加或删除信息。会话与特定的客户端关联。每次客户端访问 servlet 时,如果调用 getSession() 方法,便会检索同一个关联的 HttpSession 对象。

有关 HttpSession 所支持方法的详细信息,请参阅 HttpServlet API

在下面的示例中,service() 方法将计算用户在会话期间请求 servlet 的次数。

public void service(HttpServletRequest request, 
                    HttpServletResponse, response) 
            throws IOException
{
  // 获取会话和计数器参数特性
  HttpSession session = request.getSession (true);
  Integer ival = (Integer) 
                 session.getAttribute("simplesession.counter");
  if (ival == null) // 初始化计数器
    ival = new Integer (1);
  else // 增加计数器
    ival = new Integer (ival.intValue () + 1);
  // 在会话中设置新特性值
  session.setAttribute("simplesession.counter", ival);
  // 输出 HTML 页
  out.print("<HTML><body>");
  out.print("<center> You have hit this page ");
  out.print(ival + " times!");
  out.print("</body></html>");
}

会话生命周期

会话将跟踪用户在单个事务中在一系列页面上所进行的选择。单个事务可能包含多个任务,例如搜索商品,将其添加到购物车中,然后处理付款。会话是暂态的,发生以下情况时,会话生命周期将结束:

  • 用户离开您的站点,且用户浏览器不接受 cookie。
  • 用户退出浏览器。
  • 会话由于不活动而超时。
  • 会话已完成,servlet 使会话失效。
  • 用户退出,servlet 使用户失效。

要获得更多长期存储的持久数据,您的 servlet 应该使用 JDBC 或 EJB 向数据库中写入详细信息,并使用具有较长生命周期的 cookie 和/或用户名和密码将客户端与该数据关联起来。尽管本文中声明会话在内部使用 cookie 和持久性,但您不应将会话用作存储用户数据的一般机制。

会话跟踪的工作方式

WebLogic Server 如何获知与每个客户端关联的会话?当在 servlet 中创建 HttpSession 时,它将与一个唯一的 ID 关联。浏览器必须在其请求中提供此会话 ID,以便服务器能够再次找到该会话数据。服务器尝试通过在客户端设置 cookie 来存储此 ID。一旦设置 cookie,浏览器每次向服务器发出请求时,请求中将包括包含该 ID 的 cookie。当调用 getSession() 方法时,服务器自动解析该 cookie 并提供会话数据。

如果客户端不接受 cookie,唯一的替代方法是,将该 ID 编码到传回客户端的页面的 URL 链接中。出于此原因,在 servlet 响应中包括 URL 时,应该始终使用 encodeURL() 方法。WebLogic Server 检测浏览器是否接受 cookie,并不一定会编码 URL。当您调用 getSession() 方法时,WebLogic 会自动从编码的 URL 中解析会话 ID,并检索正确的会话数据。无论使用什么过程跟踪会话,使用 encodeURL() 方法都可以确保不干扰 servlet 代码。有关详细信息,请参阅用 URL 重写替换 Cookie

检测 会话的开始

使用 getSession(true) 方法获取会话后,可以判断该会话是否是刚才通过调用 HttpSession.isNew() 方法而创建的。如果该方法返回 true ,则客户端尚不具有有效会话,此时,它并不知道新会话已经创建。只有当服务器发布回复之后,该客户端才知道新会话的存在。

将应用程序设计为以符合业务逻辑的方式包含新会话或现有会话。例如,如果确定会话尚未启动,应用程序可以将客户端 URL 重定向至登录/密码页面,如下面的代码示例所示:

HttpSession session = request.getSession(true);
if (session.isNew()) {
  response.sendRedirect(welcomeURL);
}

登录页面上提供一个选择:登录系统或创建新帐户。您还可以使用 J2EE 标准 Web 应用程序部署描述符 web.xml 的 login-config 元素指定 Web 应用程序中的登录页面。

设置和获取会话名/值特性

可以使用 name=value 对存储 HttpSession 对象中的数据。会话中存储的数据仅能通过会话提供。要在会话中存储数据,请使用 HttpSession 接口的以下方法:

getAttribute()
getAttributeNames() 
setAttribute() 
removeAttribute()

下面的代码段显示如何获取全部的现有 name=value 对:

Enumeration sessionNames = session.getAttributeNames();
String sessionName = null;
Object sessionValue = null;

while (sessionNames.hasMoreElements()) {
  sessionName = (String)sessionNames.nextElement();
  sessionValue = session.getAttribute(sessionName);
  System.out.println("Session name is " + sessionName +
                     ", value is " + sessionValue);
}

要添加或覆盖已命名的特性,请使用 setAttribute() 方法。要一起删除已命名的特性,请使用 removeAttribute() 方法。

注意: 您可以添加 Object 的任意 Java 子项作为会话特性,并将一个名称与其关联。但是,如果您使用的是会话持久性,您的特性 value 对象必须实现 java.io.Serializable

退出和结束会 话

如果您的应用程序处理的信息比较敏感,请考虑提供退出会话的功能。在使用购物车和 Internet 电子邮件帐户时,这是一个常用功能。当同一浏览器返回服务时,用户必须登录回系统。

针对单个 Web 应用程序使用 session.invalidate()

用户身份验证信息既存储于用户会话数据中,也存储于 Web 应用程序所定位的服务器或虚拟主机的上下文中。通常用于使用户退出的 session.invalidate() 方法仅使用户的当前会话失效,用户身份验证信息仍有效,且存储于服务器或虚拟主机的上下文中。而如果服务器或虚拟主机仅承载一个 Web 应用程序,则 session.invalidate() 方法实际上会使用户退出。

在调用 session.invalidate() 之后,不要引用无效的会话。如果引用,则将引发 IllegalStateException 。下次用户从同一个浏览器访问您的 servlet 时,会话数据将丢失,调用 getSession(true) 方法时候将创建新会话。此时,您可以再次将用户发送至登录页面。

针对多个应用程序实现单一登录

如果服务器或虚拟主机是多个 Web 应用程序的目标,需要采用其他方式使用户退出所有 Web 应用程序。由于 Servlet 规范不提供用户退出所有 Web 应用程序的 API,因此提供以下方法。

weblogic.servlet.security.ServletAuthentication.logout()

从用户的会话数据中删除身份验证数据,这将使用户退出,但仍允许会话保持活动。

weblogic.servlet.security.ServletAuthentication.invalidateAll()

使所有会话无效,删除当前用户的身份验证数据。同时使 cookie 无效。

weblogic.servlet.security.ServletAuthentication.killCookie()

对 cookie 进行设置,使其在响应发送至浏览器后立即过期,从而使当前 cookie 无效。此方法依赖于响应成功到达用户浏览器。会话将保持活动,直至超时为止。

避免 Web 应用程序的单一登录

如果您不希望某 Web 应用程序参与单一登录,请为该 Web 应用程序定义另外一个 cookie 名称。有关详细信息,请参阅配置 WebLogic Server 会话 Cookie 。

配置会话跟踪

WebLogic Server 提供多种可配置的特性,它们将确定 WebLogic Server 如何处理会话跟踪。有关配置这些会话跟踪特性的详细信息,请参阅 session-descriptor

使用 URL 重写替代 Cookie

在某些情况下,浏览器可能不接受 cookie,这表明无法通过 cookie 跟踪会话。对于这种情况,URL 重写是一个解决方法,当 WebLogic Server 检测到浏览器不接受 cookie 时,会自动替换为 URL 重写。URL 重写包括将会话 ID 编码到 servlet 传回浏览器的那些网页的超链接中。当用户随后单击这些链接时,WebLogic Server 将从该 URL 中提取 ID,并查找相应的 HttpSession 。然后可以使用 getSession() 方法访问会话数据。

要在 WebLogic Server 中启用 URL 重写功能,请在 WebLogic Server 特定的部署描述符 weblogic.xml 中的 session-descriptor 元素中,将 URL-rewriting-enabled 参数设置为 true。请参阅 url-rewriting-enabled 。

为确保您的代码能够正确处理 URL 以支持 URL 重写功能,请考虑下列准则:

  • 应避免直接向输出流中写入 URL,如以下所示:
  • out.println("<a href=\"/myshop/catalog.jsp\">catalog</a>");

    而使用 HttpServletResponse.encodeURL() 方法。例如:

    out.println("<a href=\""
         + response.encodeURL("myshop/catalog.jsp") 
         + "\">catalog</a>");
  • 调用 encodeURL() 方法确定 URL 是否需要重写,如果需要,则通过在 URL 中包含会话 ID 重写该 URL。
  • 对发送重定向的 URL 以及作为响应而返回至 WebLogic Server 的 URL 进行编码。例如:
  • if (session.isNew())
    ??response.sendRedirect (response.encodeRedirectUrl(welcomeURL));  

新建会话时,即使浏览器接受 cookie,WebLogic Server 也将使用 URL 重写功能,因为在初次访问会话时,服务器无法确定浏览器是否接受 cookie。

通过检查 HttpServletRequest.isRequestedSessionIdFromCookie() 方法返回的 Boolean,servlet 可以确定给定会话是否是从 cookie 中返回的。您的应用程序可能会相应响应,或仅依赖于 WebLogic Server 的 URL 重写。

注意: CISCO 本地定向器负载均衡器要求 URL 重写中使用问号“?”分隔符。由于 W
  相关解决方案