WebObjects/Web 应用程序/开发/WO 会话
WOSession 提供了与用户使用您的应用程序相关的所有状态的封装。每个 WebObjects 应用程序都有其自己的 WOSession 子类,这是 WebObjects 中的会话跟踪与 J2EE 之间的重要区别。在 J2EE 中,HttpSession 没有子类化,所有状态都存储在 HttpSession 的 Map 中的属性中。在 WebObjects 中,会话更丰富,提供了利用作为完整类(类型化字段、方法等)的所有优势的能力。WOSessions 具有超时时间,默认情况下在 WOApplication 配置中配置。此超时时间决定服务器在没有活动请求的情况下保持会话处于活动状态的时间。当会话超时时,它将被垃圾回收。
Session session = (Session)session();
请注意,此方法仅在 WOComponent 或 WODirectAction 子类中有效。如果您想从其他地方访问会话,请从以下列表中选择一个答案
- 您的设计有误;不要从该类访问会话。
- 创建并维护一个索引,指示哪个线程正在处理哪个会话,然后您始终可以从任何地方找到当前会话。
- 仅运行单线程,并维护一个存储,指示哪个会话是当前的。
- 从调用组件或直接操作中传递会话。但是,请参阅第一项。
只需再提醒一句,不要将会话设置为 WOComponent 或 WODirectAction 的类变量,这将创建一个循环并阻止旧会话被垃圾回收。
以上情况真的吗?在 WO5 纯 Java 应用程序中,像这样的循环引用可能会为垃圾收集器增加更多工作量,但不会阻止任何内容被垃圾回收。Java 垃圾收集器应该能够很好地处理循环引用。-- JonathanRochkind
如果您想简化代码,只需在您的组件中插入以下方法(这将节省您的输入量)
public Session Session() { return (Session)this.session(); }
我们始终从一个 WOComponent 子类开始我们的项目,我们将其用作所有其他组件的超类。我们包含此方法以及其他一些有用的实用程序方法。-- JoshuaMarker
我记得关于将对 Session 的引用存储在 Session 的内部类中的警告。在另一个组件中存储对 Session 的引用是完全可以的,尽管访问器方法更好。-- BrianMarquis
我仍然认为这在 WO5 中不是问题,尽管它可能在 WO4.5 中存在。JRE 1.3.1 应该能够很好地垃圾回收循环引用,无论是否涉及内部类。但也许 JRE 没有做它应该做的事情?-- JonathanRochkind
当第一次为请求请求会话时,WebObjects 确保来自同一用户的后续所有请求都将使用相同的 WOSession 实例。WebObjects 使用以下三种技术之一来实现此会话跟踪:URL 重写、cookie 或查询字符串。
使用 URL 重写,一旦会话初始化,生成的 URL 将在 URL 路径中包含会话 ID。例如,如果您使用 WOHyperlink,生成的 URL 将类似于“http://hostname.com/cgi-bin/WebObjects/AppName.woa/1/wo/EMVnGH1g8VLOW2TRMm3Ptg/6.0.19.15.1.3.1”。此示例中的“EMVnGH1g8VLOW2TRMm3Ptg”是唯一生成的会话 ID。所有带有此会话 ID 的 URL 的请求都将附加到相同的 WOSession 实例。
Cookie 的工作原理类似,只是它们不重写 URL 来传递会话 ID,而是将会话 ID 传递给名为“wosid”的 cookie。
最后,您可以传递一个名为“wosid”的查询字符串属性,其中包含会话 ID。这通常用于调用需要访问用户会话的 DirectAction。
由于保持会话处于活动状态所需的内存使用量,因此必须仔细监控大型部署中的会话创建和持久性。通常建议尽可能减少会话创建。当使用“正常”WebObjects 技术时,这可能很困难。例如,WOHyperlink 的默认行为是在调用 WOComponent 上的操作时导致创建会话。避免创建会话的典型方法是使用 DirectAction 实现您的应用程序。DirectAction 不需要创建页面缓存来保存页面状态,因此可以用完全无状态的方式使用。仅使用 DirectAction 的缺点是您将失去更具状态的方法的好处。例如,当仅使用 DirectAction 时,您会发现您必须通过解释查询字符串变量来手动连接您的状态对象。
您可以通过调用 existingSession() 方法检查 DirectAction 中是否存在会话。如果存在会话,则将返回该会话。如果尚未创建会话,则此方法将返回 null。
调整会话超时时间会对性能产生重大影响。会话超时时间越长,会话消耗的内存就越多。在负载很重的情况下,“死”会话会不断积累,因此应将超时时间调整为尽可能低,但不会对用户使用您的应用程序的体验产生负面影响。
在 WebObjects 中,某些情况下,抛出的异常会导致会话未被检回 WOSessionStore,这将使会话死锁。这种情况的常见原因之一是使用会话的 DirectAction 抛出的异常。如果您使用 Project Wonder 的 ERXApplication、ERXSession 等,它提供了防止此问题的机制。但是,如果您使用的是没有 Project Wonder 的默认 WebObjects 安装,则需要自己解决此问题。在这种情况下,您不应该让您的 DirectAction 抛出异常。
如果您在尝试执行此操作时位于 DirectAction 方法中,请检查以下 WOAction 方法(WOAction 是 WODirectAction 的超类)
public WOSession existingSession()
根据请求恢复会话。如果请求没有会话 ID 或会话 ID 引用了不存在的会话,则此方法返回 null。若要确定会话是否未恢复,请检查请求的会话 ID,查看它是否为非空,如果是,请调用此方法检查其结果。
返回值:一个 WOSession 对象,它代表向特定客户端授予对 WebObjects 应用程序及其资源的访问权限的期间
如果您不在 DirectAction 方法中,请查看 WOContext 的方法
public boolean hasSession()
如果接收上下文中存在会话,则返回 true,否则返回 false。