摘要
在我们的 Web 应用程序中,当用户单击"比页面加载更快"时,显然浏览器向用户显示第一个请求(根据我们收到的一些错误消息)。我本以为这是第二个请求。
更多背景信息
我们有一个 Struts1 Web 应用程序。在用户会话中,我们放置了用户交互的当前上下文。
request.getSession().setAttribute("context", <something>);
例如,应用显示主记录列表,上下文包含有关用户的信息。当用户单击主记录时,我们将有关该记录的信息保存在用户会话对象中。在 JSP 中,我们经常将上下文对象分配给局部变量。这需要强制转换为特定类型(例如 MasterRecordDTO
或UserDTO
):
<% MasterRecordDTO dto = (MasterRecordDTO) request.getSession().getAttribute("context"); %>
然后,用户可以向下钻取到该主记录的详细信息视图。我们有一个面包屑显示像list > master > detail
.这些链接使用户可以使用痕迹导航进行导航。
现在,当用户首先单击"master"并快速单击"列表"时,他会得到一个ClassCastException,说
"UserDTO cannot be cast to MasterRecordDTO"
在 MasterRecord-JSP 中,这意味着当 MasterRecord-JSP 在第一个请求中分配 dto
变量时,第二个请求已经将 context
会话属性设置为UserDTO
对象。
问题
我本以为浏览器会"放弃"第一个请求,并向用户显示第二个请求的结果(本例中的主记录列表)。谁能向我解释一下?
更新
痕迹导航链接位于另一个 HTML 框架中。我们在 Internet Explorer 7 中遇到了这个问题。我用Firefox 11尝试过,但显然它甚至没有提交第二次点击。
一般的并发编程情况。
浏览器同时向服务器发送2个请求,服务器使用2个线程处理2个请求。
- 请求/线程 1 将会话属性
context
设置为MasterRecordDTO
- 请求/线程 2 然后将其更改为
UserDTO
(这是问题的根源) - 请求/线程 1 继续运行,这将导致发生
ClassCastException
。 - 请求/线程 2 继续运行,它将生成对客户端的成功响应。(但浏览器不显示)
的行为不受应用程序控制,它只显示响应 1 的结果(有时可能是响应 2,这也是并发情况,因为当前大多数浏览器都是多线程设计的)。
尝试使用请求范围来存储此类context
信息以获得预期结果。