一个Java Web应用程序的多标签问题-混合来自两个不同记录的数据



问题:每当我们在浏览器的两个不同选项卡中为同一会话保存两个不同记录的数据时,相应保存的记录的数据就会混淆。

场景:1) 选项卡1:打开浏览器并登录到应用程序,然后进入搜索屏幕。(在我们的案例中,担保人搜索屏幕)。

2) 选项卡2:在同一浏览器中打开另一个浏览器选项卡,复制上一步的URL并将其粘贴到当前选项卡中,现在在两个选项卡中打开搜索屏幕。

3) 返回表1,搜索一个担保人(例如:编号为34526的担保人),在搜索屏幕中获得结果后打开一次。

4) 然后转到表2,搜索另一个担保人记录并打开该记录。

5) 现在单击编辑按钮编辑在Tab2中打开的记录,然后返回Tab1,不编辑Tab2中的数据。

6) 现在点击编辑按钮编辑在Tab1中打开的记录,然后进行修改并在此屏幕中执行一些操作,如"保存"操作,同时转到Tab2并点击此屏幕上的"保存"。现在,我们点击了Tab1上的保存按钮,同时在Tab1完成保存操作之前,我们还在Tab2中执行了另一个操作(即save)。

7) 现在,此时两个屏幕的数据都混淆了(这不是一种正确的行为)。在这种情况下,数据不应该混淆,应该为相应的记录正确保存。请注意,在上述场景中,两个选项卡的打开屏幕将相同,但记录不同。(例如:打开"编辑担保人"屏幕,但有两个不同的担保人记录)。

客户首选解决方案:

应用程序应允许在不中断应用程序流的情况下对在多个选项卡中打开的记录进行更改。在这种情况下,登录到应用程序的用户将是相同的,并且应用程序应该允许多选项卡功能,而不会混淆数据。

问题的可能根本原因是:

1) IE 7及以上版本的浏览器在整个浏览器中保持单一会话,即使你打开新窗口,它也会有相同的会话。由于我们使用的是IE8,它甚至可以通过不同的选项卡来维护单个会话。这可能会造成这个问题。

我们对上述问题进行了一些研究,也查看了一些博客,但我们无法找到问题的正确解决方案。

我们检查了一些东西来解决这个问题,比如:

1) SessionStorage概念,可从HTML5中获得,并可从IE8+浏览器中支持,但此解决方案不支持我们上面提到的要求。如果有人在这个帮助下得到了上述结果,请告诉我们。

2) 我们找到了另一个解决方案:URL重写-(添加会话详细信息和一些唯一的详细信息以区分会话,并在每个页面中维护一些隐藏字段以跟踪会话)-但这非常复杂,我们也不确定这是否解决了上述问题。如果在这方面有任何建议,请告诉我们。

我们还尝试了一些JavaScript编码的例子,但没有得到所需的解决方案。

如果有人已经在他们的应用程序中实现了,我们期待一些指导或类似的解决方案。

您是否尝试将表单bean的范围设置为请求?默认情况下,struts的表单bean是会话范围的。因此,您发布回服务器的bean在选项卡之间共享。如果将作用域设置为request,那么在不同的选项卡中会有不同的表单bean。这将确保当用户点击保存时,数据不会混淆。

我在几个struts应用程序中看到过这个问题,这些应用程序要求用户在多个页面上填充数据(用户在一个页面上填写数据,点击下一个…到达最后一个页面,点击保存,然后数据保存在数据库中)。当用户单击next转到下一个页面时,当前页面(表单)数据将保存在HttpSession中(如果bean范围是session,Struts会自动执行此操作)。当用户在多个选项卡或浏览器窗口中打开应用程序(假设用户对多个窗口使用相同的浏览器(例如IE))并对不同记录的表单执行操作时,数据会在同一会话中被保存/覆盖并损坏。你的情况也类似。

正如您正确指出的那样,jsessionID的实现有点复杂,因为如果您在网页上呈现一些链接(从xml文件指向应用程序其他部分的链接),您需要将jsessionID嵌入URL中,否则服务器将分配一个新的jsessionID,并将用户重定向到登录页面(假设您的企业应用程序要求用户首先登录)(动态生成的链接将嵌入jsessionID)。这种方法的第二个问题是:如果用户右键单击任何链接(假设jsessionID嵌入其中),选择在新窗口/选项卡中打开,然后导航到其他记录进行编辑,则您的数据将被损坏(请注意,当用户为链接选择在新选项卡中打开时,该链接的URL将已经具有来自父窗口/选项卡的相同jsessionID)。

为了解决这个问题,您必须在应用程序中进行一些设计更改。以下是可能的方法。

您可以将数据存储在缓存中,而不是存储在HttpSession中(您可以有自己的逻辑将数据存储为键值对,如下所述)。我想你必须遵循以下步骤:a) 将bean作用域更改为从会话请求。b) 每个窗口/选项卡都有一个唯一的标识符。您可以对其使用windows.name属性。所有主要浏览器都支持此属性。每次单击下一个/上一个/保存时,都应将此选项卡/窗口名称发送到服务器。c) 在服务器端存储数据,可以遵循以下方法(可能不是最好的方法,请随意调整。:-)

    HashMap -> key will be the jessionID and value will be another HashMap.
          - HashMap(value of the first Map) -> key will be tab/windows name sent from the browser. Value will be another HashMap.
                   - HashMap (value of the second map) -> Key will be form name. Value will be the actual form. (this map will have only one entry, if you have only one form).
d) Once you approach on the last page, get all the forms from the Map for the desired tab/window and save in the database.

对于上面提到的(c)点,您可以使用数据库来存储中间数据。这两种方法都有利弊。i) 与数据库相比,在Map/data Structure中存储/检索数据更快。ii)在数据结构中存储数据消耗堆上的空间。但是,从现在起,您将数据存储在会话中,因此这应该不会成为问题。iii)如果存储在DS中,数据会在服务器崩溃的情况下丢失。可以从数据库中检索数据。

最新更新