Model view controller 控制器(SpringManagedBean)作用域问题:单例、请求还是会话?

Model view controller 控制器(SpringManagedBean)作用域问题:单例、请求还是会话?,model-view-controller,spring,controller,javabeans,Model View Controller,Spring,Controller,Javabeans,这个问题有点长,因为它是概念性的。我希望这本书读得不错:) 我在一个性能关键的SpringMVC/Tiles web应用程序中工作(10000个用户典型负载)。我们加载一个更新员工屏幕,其中我们加载一个员工详细信息屏幕(绑定到员工业务对象),以便通过MultiActionController进行更新。此屏幕上有多个选项卡,但只有tab1具有可更新数据。其余的标签页基本上都是只读的,仅供参考 不用说,我们决定以一种惰性的方式加载这些只读选项卡,即,当每个选项卡被激活时,我们触发一个ajax调用(一

这个问题有点长,因为它是概念性的。我希望这本书读得不错:)

我在一个性能关键的SpringMVC/Tiles web应用程序中工作(10000个用户典型负载)。我们加载一个更新员工屏幕,其中我们加载一个员工详细信息屏幕(绑定到员工业务对象),以便通过MultiActionController进行更新。此屏幕上有多个选项卡,但只有tab1具有可更新数据。其余的标签页基本上都是只读的,仅供参考

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

现在,我左右为难。我制作了另一个多动作控制器,名为“AjaxController”,用于处理这些ajax调用。现在,我的问题是:

  • 此控制器的最佳范围是什么
  • 想法:如果我将其限定为请求范围,那么10000个用户可以一起创建10000个bean实例:内存问题。如果我将其设置为会话范围,那么每个用户会话将创建一个会话。这意味着,当10000名用户登录到该应用程序时,无论他们是否点击了AjaxController方法,他们都将拥有一个bean

  • 那么,singleton是该控制器的最佳作用域吗
  • 想法:spring启动时将创建一个单例bean,并且将始终提供这个实例。听起来不错

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

  • 我可以手动将单例设计模式实现到AjaxController中吗
  • 想法:如果我控制了创作,那该怎么办:基本上是做GoF单件。那么范围规范能做什么呢?作用域会话/请求肯定不能创建多个实例,不是吗

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


    关键提示:AjaxController bean不是在其他任何地方注入的,它是孤立存在的。它的方法是通过ajax调用命中的。

    如果我这样做的话,我肯定会使LazyLoadController成为单例,其中没有静态方法,也没有任何状态

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

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

    这就是做这种事情的良好实践。有一些事情需要澄清,以便为您的案例提供更具体的答案。我是否正确理解了AjaxController的典型用例是将一些请求传递给LazyLoadController以获取选项卡数据?请在评论或您的问题中提供详细信息,以便我更新我的答案


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

    我犯了一个巨大的错误。LazyLoadController是AjaxController。我在开始写问题时想到了一个名字,然后在回答问题时又回到了另一个名字。抱歉,我已经编辑了这篇文章。是的,您的用例是正确的。事实上,我确实有一个服务层,它正是这样做的,而这个AjaxController只是充当一个请求调度器和响应处理程序。我对冲突情景仍有一些怀疑。目前,我的AjaxController是单例的,具有处理请求和与服务层交互的静态方法。这个设置有问题吗?我明白了。更新了我的答案,解释了为什么静态方法是错误的。