线程安全struts web应用程序与弹簧

时间:2016-02-08 16:26:52

标签: java spring multithreading struts2 cdi

在struts 2和基于弹簧网的应用程序中,请考虑以下示例。

struct有一项操作可将BookManager本书退回给客户。它从服务层获取地图,即Spring {/ p>为Map

injected

服务层从DB获取图书列表并返回MAP。

public class BookManager extends ActionSupport {

   //with setter and getter
   private Map<String, BookVO> books;

   @inject
   BookService bookservice

   @Action("book-form")
   public String form(){    
       setBooks(bookservice.getAllBooks());
   }

}

我测试过并发现上述实现不是线程安全的

  1. 我可以通过从@Named public class BookService(){ private Map<String,BookVO> books; public Map<String,BookVO> getAllBooks(){ books = new HashMap<String,BookVO>(); //fill books from DB return books; } } 删除私有字段books来使代码线程安全,并像方法BookService一样使用它。为什么这个改变使代码线程安全?
  2. struts动作是线程安全的,不应该确保偶数非线程安全弹簧服务以线程安全的方式运行。
  3. 如果我在我的操作中使用非线程安全版本的服务,通过创建HashMap<String,BookVO>() books = new HashMap<String,BookVO>();服务对象而不是使用spring inject,我将面临任何问题。为什么?如果服务不是线程安全的,为什么创建一个新实例并调用它将是线程安全的!

1 个答案:

答案 0 :(得分:1)

  

我可以通过从BookService中删除私有字段书来使代码线程安全,并像方法HashMap()books = new HashMap();一样使用它。为什么这个改变使代码线程安全?

因为方法级变量是线程安全的,而类级变量不是。

  

struts动作是线程安全的,这不应该确保甚至非线程安全弹簧服务以线程安全的方式运行吗?

不。这取决于。

  

如果我在我的操作中使用非线程安全版本的服务,通过创建一个新的服务对象而不是使用spring注入,我将面临任何问题。为什么?如果服务不是线程安全的,为什么创建一个新实例并调用它将是线程安全的!

如果您在操作中手动实例化它,那么您正在创建该操作的私有实例,由于操作是ThreadLocal,因此是线程安全的,并由您管理(这意味着您的BookService类具有其中有一些@Inject,容器无法解析它们。)

如果您拥有由容器管理的DI,则该实例不是线程安全的;您正在使用的内容(@Inject@Named)不仅仅是“Spring”,它是Java EE,它是JSR-330(依赖注入)的实现,仅在支持CDI的应用程序中可用(JSR) -299)。
CDI bean不是线程安全的。您应该使用EJB3's @Singleton for this to be thread-safe,但实际上您不需要在类级别保留该属性,因为它仅用于返回,然后在下次时被覆盖。

BTW考虑使用Struts2 CDI-plugin参考CDI(在JBOSS中焊接),值得一试。