请在Spring MVC + Apache Tiles中等待页面

时间:2012-03-02 18:27:23

标签: spring-mvc thread-safety pleasewait

我使用Spring MVC 3 + Tiles作为webapp。我的操作很慢,我喜欢请等待页面。

有两种主要方法可以等待页面,我知道:

  1. 长期请求:渲染并刷新"请等待"该页面的一部分,但在操作完成之前不要完成请求,此时您可以使用一些javascript流出其余的响应来重定向或更新页面。
  2. 立即返回,并在后台线程上开始处理。客户端轮询服务器(在javascript中,或通过页面刷新),并在后台线程完成时重定向。
  3. (1)很好,因为它保持了所有单线程的操作,但是Tiles看起来不可能,因为每个JSP必须在页面组装并返回给客户端之前完整地完成呈现。

    所以我开始实施(2)。在我的实现中,第一个请求使用Spring的@Async注释在后台线程上开始操作,该注释返回Future<Result>。然后返回&#34;请等待&#34;页面给用户,每隔几秒刷新一次。

    当刷新请等待页面时,控制器需要检查后台线程的进度。这样做的最佳方式是什么?

    1. 如果我将Future对象直接放在Session中,那么轮询请求线程可以将其拉出并检查线程的进度。但是,这并不意味着我的会话不可序列化,因此我的应用程序无法部署多个Web服务器(不需要粘性会话)?
    2. 我可以在Session中放置某种状态标志,并让后台线程在完成后更新Session。我非常担心将HttpSession对象传递给非请求线程会导致难以调试错误。这是允许的吗?任何人都可以引用任何文件吗?当会话在内存中时,它工作正常,但是如果会话存储在数据库中会怎么样?如果我有多个Web服务器怎么办?
    3. 我可以在我的数据库中放置某种状态标志,键入会话ID或慢速操作的其他方面。在我的域数据库中存在会话数据似乎很奇怪,而不是在会话中,但至少我知道数据库是线程安全的。
    4. 我错过了另一种选择吗?

1 个答案:

答案 0 :(得分:1)

Spring MVC部分问题相当简单,因为问题与Spring MVC无关。请参阅此答案中的可能解决方案:https://stackoverflow.com/a/4427922/734687

正如您在代码中看到的那样,作者使用tokenService来存储未来。实现不包括在内,这里的问题就像您已经知道的那样,在您想要进行故障转移时开始。

  • 无法序列化未来并让它跳转到第二个服务器实例。线程在某个实例中执行,因此必须留在那里。所以会话存储是没有选择的。
  • 在示例链接中,您可以使用令牌服务。这通常只是一个HashMap,您可以在其中存储对象,然后通过令牌(String标识符)再次访问它。但同样,当tokenService是单例时,这只适用于同一个Web应用程序。

解决方案不是为了保存未来,而是为了工作的状态(在工作中,完成后,结果失败)。即使查询会话和执行线程在不同的机器上,状态也应该是可访问的并且可以序列化。但是你会怎么做?这可以通过将其存储在数据库或文件系统(上面的示例,您可以检查zip文件是否可用)或键/值存储或缓存或公共对象存储(Terracota)中来实现, ...

实际上,每个批处理框架(例如Spring Batch)都以这种方式工作。它将作业的当前状态存储在数据库中。您担心将域数据与操作数据混合在一起。但是大多数应用程在大型应用程序上,可以使用两个数据库实例,操作数据和域数据。

所以我建议您将工作的状态和结果保存在数据库中 希望有所帮助。