控制器(Spring Managed Bean)范围问题:单例,请求还是会话?

时间:2010-07-09 06:30:36

标签: model-view-controller spring controller javabeans

问题有点长,因为它是概念性的。我希望这不是一个糟糕的读物:)

我正在使用性能至关重要的Spring MVC / Tiles Web应用程序(10,000个用户的典型负载)。我们加载更新员工屏幕,我们在其中加载员工详细信息屏幕(绑定到员工业务对象)以通过MultiActionController进行更新。此屏幕上有多个选项卡,但只有tab1具有可更新数据。其余的标签是只读的东西,基本上可供参考。

毋庸置疑,我们决定以懒惰的方式加载这些只读选项卡,即,当每个选项卡被激活时,我们触发ajax调用(一次性)以从服务器获取数据。我们不通过更新视图加载方法加载所有内容。请记住:这是一次只读数据。

现在,我处于两难境地。我已经创建了另一个多路动作控制器,名为“AjaxController”来处理这些ajax调用。现在,我的问题:

  1. 这个控制器的最佳范围应该是什么?
  2. 思考:如果我将其作为请求范围,那么10,000个用户一起可以创建10,000个这个bean的实例:内存问题。如果我将其作为会话范围,那么将为每个用户会话创建一个。这意味着,当10,000个用户登录到应用程序时,无论他们是否使用AjaxController方法,他们都将拥有一个bean。

    1. 然后,单身是这个控制器的最佳范围吗?
    2. 思考:弹簧靴时会创建一个单独的bean,这个实例将在整个过程中提供。听起来不错。

      1. 处理程序方法(如fetchTab7DataInJsonFormat)是否应该是静态的并附加到类中?
      2. 思考:在这种情况下,是否可以在静态方法上与语境冲突?例如:scope =“session”/“request”+静态方法有意义吗?我问,因为即使每个用户会话都有自己的AjaxController bean,处理程序方法实际上附加到类,而不是实例。另外,scope =“singleton”+静态处理程序方法是否有意义?

        1. 我可以手动将单例设计模式实现到AjaxController中吗?
        2. 思考:如果我控制创作怎么办:基本上做GoF单身。然后范围规范可以做什么?范围会话/请求肯定无法创建多个实例吗?

          1. 如果通过任何机制(bean规范/设计模式/静态方法),我确实设法有一个AjaxController实例:这些STATIC方法是否需要同步?我想不是,因为即使STATIC处理程序方法可以与需要时间的服务(与DB / WS / MQ等交谈)进行通信,我认为每个请求线程进入静态方法都会被它们的线程ID返回吗?它不像user1进入静态方法,然后user2在返回user1之前进入静态方法,然后它们都得到一些乱码数据?这可能很傻,但我想确定。
          2. 我很困惑。我基本上只需要一个控制器bean的单个实例来为所有客户端提供所有请求。

            严重注意:AjaxController bean在其他任何地方都不是INJECTED,它是隔离的。它的方法是通过ajax调用来实现的。

1 个答案:

答案 0 :(得分:3)

如果我这样做,我肯定会在没有静态方法且没有任何状态的情况下制作LazyLoadController单例。

另外,你绝对不应该手动实例化单例,最好使用Spring的通用机制,让框架控制一切。

总体思路是避免在控制器中使用任何静态方法和/或持久数据。正确的机制是使用一些服务bean为请求生成数据,因此控制器充当请求参数调度程序以将数据提取到视图中。控制器中不允许存在可变状态或同时不安全的东西。如果某些组件是特定于用户的,则Spring的AOP系统会根据会话/请求提供组件注入。

这就是做这样的事情的好习惯。有一些事情需要澄清,以便为您的案例提供更具体的答案。我是否理解正确的用例是AjaxController会将一些请求传递给LazyLoadController来获取标签数据?请在评论或您的问题中提供相关详细信息,以便我可以更新我的答案。

在控制器中使用静态方法的问题在于,您必须自己管理并发安全,这不仅容易出错,而且还会降低整体性能。 Spring在自己的线程中运行每个请求,所以如果两个并发调用需要使用一些静态方法并且有共享资源(所以你需要使用synchronize语句或锁),其中一个线程将不得不等待另一个完成工作在受保护的街区。另一方面,如果您使用无状态服务并避免拥有可能为多个调用共享的数据,则可以提高性能并且无需处理并发数据访问。