重要会话语义
多线程问题
在同一时间多个 servlet 执行请求的线程可能都有到同一会话的活跃访问。容器必须确保,以一种线程安全的方式维护表示会话属性的内部数据结构。开发人员负责线程安全的访问属性对象本身。这样将防止并发访问HttpSession对象内的属性集合,消除了应用程序导致破坏集合的机会。
分布式环境
在一个标识为分布式的应用程序中,会话中的所有请求在同一时间必须仅被一个 JVM 处理。容器必须能够使用适当的 setAttribute 或 putValue 方法把所有对象放入到 HttpSession 类实例。以下限制被强加来满足这些条件:
- 容器必须接受实现了 Serializable 接口的对象。
- 容器可以选择支持其他指定对象存储在 HttpSession 中,如Enterprise JavaBeans 组件和事务的引用。
- 由特定容器的设施处理会话迁移。
当分布式 servlet 容器不支持必需的会话迁移存储对象机制时容器必须抛出 IllegalArgumentException。
分布式 servlet 容器必须支持迁移的对象实现 Serializable 的必要机制。
这些限制意味着开发人员确保除在非分布式容器中遇到的问题没有额外的并发问题。
容器供应商可以确保可扩展性和服务质量的功能,如负载平衡和故障转移通过把会话对象和它的内容从分布式系统的任意一个活跃节点移动到系统的一个不同的节点上。
如果分布式容器持久化或迁移会话提供服务质量特性,它们不限制使用原生的 JVM 序列化机制用于序列化 HttpSession 和它们的属性。如果开发人员实现 session 属性上的 readObject 和 writeObject 方法,他们也不能保证容器将调用这些方法,但保证 Serializable 结束它们的属性将被保存。
容器必须在迁移会话时通知实现了 HttpSessionActivationListener 的所有会话属性。它们必须在序列化会话之前通知钝化监听器,在反序列化之后通知激活监听器。
写分布式应用的开发人员应该意识到容器可能运行在多个 Java 虚拟机中,开发人员不能依赖静态变量存储应用状态。他们应该用企业 Bean 或数据库存储这种状态。
客户端语义
由于 cookie 或 SSL 证书通常由 Web 浏览器进程控制,且不与浏览器的任意特定窗口关联,从客户端应用程序发起的到 servlet 容器的请求可能在同一会话。为了最大的可移植性,开发人员应该假定客户端所有窗口参与同一会话。