为什么struts动作类是单例?
实际上我明白它是多线程的。但是当有数千个请求执行相同的操作时,我们将同步用于防止线程问题,那么它不能提供良好的性能bcoz线程进入等待状态并且需要时间来进行处理。
这是否可以从动作类中删除单例?
了解更多信息请访问:http://rameshsengani.in
答案 0 :(得分:21)
你问为什么Action类是单例,但我认为你也有一些理解线程安全性的问题所以我会尝试解释它们。
首先,Struts Action类没有实现为单例,框架只使用它的一个实例。但是因为只有一个实例用于处理所有传入的请求,所以必须注意不要在非线程安全的Action类中执行某些操作。但问题是:默认情况下,Struts Action类不是线程安全的。
Thread safety表示可以在多线程环境中安全地使用一段代码或对象。 Action类可以安全地用在多线程环境中,你可以同时在一千个线程中使用它而没有任何问题......如果你正确实现它 。
必须以线程安全的方式对操作进行编程,因为控制器将为多个同时请求共享同一实例。这意味着您应该考虑以下项目进行设计:
实例和静态变量不得用于存储与特定请求状态相关的信息。它们可用于跨同一行动的请求共享全局资源。
如果这些资源需要保护,则必须同步对其他资源(JavaBeans,会话变量等)的访问。 (但一般情况下,资源类应设计为在必要时提供自己的保护。
您可以通过派生并创建自己的Struts Action来使用它。当您这样做时,您必须注意遵守上述规则。这意味着像这样的NO-NO:
public class MyAction extends Action {
private Object someInstanceField;
public ActionForward execute(...) {
// modify someInstanceField here without proper synchronization ->> BAD
}
}
除非你在上面的代码中做错了,否则你不需要同步Action类。问题在于执行操作的切入点是execute
方法。
此方法接收所有需要的参数。您可以在execute
方法中同时执行一千个线程而不会出现问题,因为每个线程都有自己的执行堆栈用于方法调用,但不适用于堆中的数据(如someInstanceField
),在所有线程之间共享。
在修改someInstanceField
时没有正确的同步,所有线程都可以随意使用它。
所以,是的,Struts 1 Action类不是线程安全的,但这是因为你不能安全地将状态存储在它们中(即使它们成为statefulf),或者如果你这样做必须正确同步。
但是如果你保持你的Action类实现无状态,你就可以了,不需要同步,线程也不会等待。
为什么struts动作类是单例?
这是设计的。 JavaDoc再次解释了它:
Action是传入HTTP请求的内容与应该执行以处理此请求的相应业务逻辑之间的适配器
请求参数绑定到Web层,您不希望将该类型的数据发送到业务逻辑类中,因为这会产生紧密耦合 在这两个层之间,这将使您无法轻松重用业务层。
因为将Web对象转换为模型对象(我并不是说ActionForm bean在这里)应该是Action类的主要目的,所以它们不需要维护任何状态(并且不应该),并且没有理由拥有这些家伙的更多实例,所有人都做同样的事情。只有一个人会这样做。
如果您希望通过将信息保存到数据库中,可以安全地维护模型中的状态,或者您可以使用http会话维护Web状态。在Action类中维护状态是错误的,因为这引入了同步化的需要,如上所述。
有没有办法从动作类中删除单例?
我猜你可以扩展Struts并覆盖RequestProcessor.processActionCreate的默认行为,为每个请求创建一个Action 但这意味着在Struts之上添加另一个层来改变其“正常”行为。我已经看到这样的东西在一些应用程序中变坏了所以我不推荐它。
我的建议是让你的Action类保持无状态,并选择为它创建的单个实例。
如果您的应用是新的,并且您绝对需要有状态的操作,我想您可以选择Struts 2(他们在那里更改了设计,现在每个请求都有一个Action实例)。 But Struts 2 is very different from Struts 1因此,如果你的应用程序已经过时,可能很难迁移到Struts 2。
希望现在能说清楚。
答案 1 :(得分:2)
这已在Struts2 http://struts.apache.org/release/2.1.x/docs/comparing-struts-1-and-2.html
中发生了变化* Struts 2 Action对象针对每个请求进行实例化,因此没有线程安全问题。 (实际上,servlet容器会为每个请求生成许多丢弃对象,而另外一个对象不会对性能造成影响或影响垃圾回收。)*
答案 2 :(得分:1)
我对struts知之甚少,但看起来this changed in Struts 2,所以也许你应该切换到Struts 2?