我有一个Java Web应用程序,它在会话中存储一些数据。当用户与应用程序交互时,会话中的数据发生变化(例如,流程由控制器管理,每个控制器具有多个表单页面,在每个表单页面上,一些数据在会话中更新,流程转到下一个表单页面)。
问题是一些用户正在向应用程序打开多个选项卡,每个选项卡在流程中都有不同的步骤。此时会话中的数据混乱,因为选项卡共享同一会话(应用程序使用cookie托管会话)。
告诉用户使用不同的浏览器以避免共享相同的会话ID(例如,一个Firefox窗口和一个IE窗口)不是一个选项,因为在某些时候肯定会有人忘记这样做而是使用标签,从而弄乱了他们的数据。
添加一些检测从另一个选项卡请求另一个流的验证,并向用户显示一条消息,说这是不允许的,因为它对用户很生气,我们不希望这样做吗? :d
事实是,使用另一个选项卡对用户非常有用,因为它们在使用应用程序时更有效,所以我保留了这个选项。但现在的问题是如何最好地管理更多标签的一个会话数据?
我想到的是让控制器在启动流程时生成令牌,并将此令牌传递给每个表单页面,然后将其发送回标识自身。如果另一个选项卡在存在正在进行的流时请求相同的控制器操作,则生成另一个标记并将其传递。
基本上,我希望每个流都有一个令牌,在会话中我不仅会保留一组数据,而是为每个令牌提供一组数据,然后根据令牌匹配请求。
现在的问题是这种方法需要对应用程序进行大量的重写,我想知道是否有管理这种情况的最佳实践,或者有人可以建议其他方法。我对这些想法持开放态度。
你遇到过这种情况吗?你是怎么处理的?答案 0 :(得分:14)
这通常是通过为每个选项卡/窗口分配windowId并在每个请求上传递它来完成的。 Jsf通过orchestra支持此功能。 Spring mvc将在下一个版本中支持它。
我最近需要一个简单的案例,所以我自己实现了它。花了半个小时。但是,我的范围非常有限:
windowId
,然后将其返回以获取下一个请求。第一次 - 生成它。Map<String, Object>
放在密钥为windowId
答案 1 :(得分:0)
这正是Seam创建的处理方式。在Seam中有一个名为Conversation的概念,它基本上完全按照你的解释。对话基本上是一种将会话划分为多个片段的方法,这些片段可以在某个超时时间到期。你可以查看org.jboss.seam.core.Manager类的源代码,看看它是如何实现的并得到启发;)
答案 2 :(得分:0)
根据应用程序的复杂程度,您可能需要调查应用程序中的实施选项卡。这使您可以批量控制流,同时仍然为用户提供他们想要的功能。我认为这是最强大的解决方案,因为你不会依赖浏览器处理会话的方式,最大限度地减少“已知未知数”的数量。
当然,根据应用程序的结构,这可能会有很大的前期成本。如果没有关于您的应用的更多信息,您就是最适合决定的人。
答案 3 :(得分:0)
您还可以尝试将您的应用程序包装在Adobe Air
中然后将您的Web应用程序限制为只能通过此方式访问。通过这样做,您不需要考虑Web浏览器碎片及其独特的行为。