跨分布式 Web 会话的可变对象状态复制



我想知道为什么在HTTP会话中存储可序列化对象时没有关于不可变性属性重要性的单一通知?我试图检查JSF和Servlet API规范,但找不到任何相关的内容。

在基于 JSF 的集群应用程序中,我看到了一个特定问题@SessionScoped其中托管 Bean 是可变的,即用户修改的参数存储为该托管 Bean 的字段。

当"拥有"会话的节点(由于 servlet API 规范中的粘性要求(死亡并且不同的节点开始接管会话服务时,问题就开始了,最新状态丢失。实际上,仅复制初始状态。我相信这是因为托管 bean 仅在首次创建时才放置在会话中(并复制到备份节点(,至少我在 Websphere 上执行的测试证实了这一点。

虽然人们可以争论这是否是一个好的设计,但JSF甚至Servlet API仍然允许它发生。

我还在 Oracle 文档中发现了一些注释:

作为一般规则,如果可能,所有会话属性都应被视为不可变对象。这可确保开发人员在更改属性时有意识地意识到。对于可变对象,修改属性通常需要两个步骤:修改属性对象的状态,然后通过调用javax.servlet.http.HttpSession.setAttribute((手动更新具有修改的属性对象的会话。这意味着,如果属性值已更改,应用程序应始终调用setAttribute((,否则,修改后的属性值将不会复制到备份服务器。


除了如上所述手动更新属性之外,是否有任何干净的解决方案,最好是惯用的 JSF 方式?

在 WebSphere Liberty 中,有一个名为 writeContents = "GET_AND_SET_ATTRIBUTES" 对于可变会话对象。详情请参阅:

https://github.com/OpenLiberty/open-liberty/issues/2802

https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.liberty.autogen.nd.doc/ae/rwlp_config_httpSessionCache.html

相同的属性适用于数据库持久性。

最新更新