我正在将 Spring MVC 3 + Tiles 用于 web 应用程序。我的操作很慢,我想要一个请稍候页面。
我知道有两种主要的方法来请等待页面:
- 长期请求:渲染并刷新页面的“请稍候”位,但在操作完成之前不要完成请求,此时您可以使用一些 javascript 流出剩余的响应以重定向或更新页面。
- 立即返回,并在后台线程上开始处理。客户端轮询服务器(在 javascript 中,或通过页面刷新),并在后台线程完成时重定向。
(1) 很好,因为它使操作全部保持单线程,但对于 Tiles 似乎不可能,因为每个 JSP 必须在页面组装并返回给客户端之前完成完整呈现。
所以我开始实施(2)。在我的实现中,第一个请求使用 Spring 的@Async
注释在后台线程上启动操作,该注释返回一个Future<Result>
. 然后它会向用户返回一个“请稍候”页面,该页面每隔几秒刷新一次。
当请等待页面刷新时,控制器需要检查后台线程的进度。这样做的最佳方法是什么?
- 如果我
Future
直接将对象放入 Session 中,那么轮询请求线程可以将其拉出并检查线程的进度。但是,这是否意味着我的 Sessions 不可序列化,所以我的应用程序不能部署在多个 Web 服务器上(不需要粘性会话)? - 我可以在 Session 中放置某种状态标志,并让后台线程在 Session 完成时更新它。我非常担心将 HttpSession 对象传递给非请求线程会导致难以调试的错误。这是允许的吗?任何人都可以引用任何文件吗?当然,当会话在内存中时它工作得很好,但是如果会话存储在数据库中呢?如果我有多个网络服务器怎么办?
- 我可以在我的数据库中放置某种状态标志,键入会话 ID,或慢速操作的其他方面。在我的域数据库中而不是在会话中有会话数据似乎很奇怪,但至少我知道数据库是线程安全的。
- 我还有其他选择吗?