spring的controller是單例模式,可是是多線程,各個線程之間不影響

spring mvc 的Controller類默認Scope是單例(singleton)的

使用Spring MVC有一段時間了,以前一直使用Struts2,在struts2中action都是原型(prototype)的, 說是由於線程安全問題,對於Spring MVC中bean默認都是(singleton)單例的,那麼用@Controller註解標籤注入的Controller類是單例實現的?java

 

測試結果發現spring3中的controller默認是單例的,如果某個controller中有一個私有的變量i,全部請求到同一個controller時,使用的i變量是共用的,即如果某個請求中修改了這個變量a,則,在別的請求中可以讀到這個修改的內容。 如果在@Controller以前增長@Scope(「prototype」),就能夠改變單例模式爲多例模式web

如下是測試步驟,代碼與結果.spring

1. 若是是單例類型類的,那麼在Controller類中的類變量應該是共享的,若是不共享,就說明Controller類不是單例。如下是測試代碼:spring-mvc

 
  1. import javax.servlet.http.HttpServletRequest;安全

  2. import javax.servlet.http.HttpServletResponse;服務器

  3.  
  4. import org.springframework.stereotype.Controller;mvc

  5. import org.springframework.web.bind.annotation.RequestMapping;app

  6. import org.springframework.web.bind.annotation.ResponseBody;測試

  7. @Controllerspa

  8. public class ExampleAction {

  9. private int singletonInt=0;

  10. @RequestMapping(value = "/test")

  11. @ResponseBody

  12. public String singleton(HttpServletRequest request,

  13. HttpServletResponse response) throws Exception {

  14. String data=request.getParameter("data");

  15. if(data!=null&&data.length()>0){

  16. try{

  17. int paramInt= Integer.parseInt(data);

  18. singletonInt = singletonInt + paramInt;

  19. }

  20. catch(Exception ex){

  21. singletonInt+=10;

  22. }

  23. }else{

  24. singletonInt+=1000;

  25. }

  26. return String.valueOf(singletonInt);

  27. }

  28. }

 

分別三次請求: http://localhost:8080/example/test.do?data=15

獲得的返回結果以下。

第一次: singletonInt=15

第二次: singletonInt=30

第三次: singletonInt=45

從以上結果能夠得知,singletonInt的狀態是共享的,所以Controller是單例的。

2. 若是Controller類是單例,那麼多個線程請求同一個Controller類中的同一個方法,線程是否會堵塞

 

 
  1. @RequestMapping(value = "/sleepdata")

  2. @ResponseBody

  3. public String switcher(HttpServletRequest request

  4. , HttpServletResponse response)

  5. throws Exception {

  6. String sleep = request.getParameter("sleep");

  7. if (sleep.equals("on")) {

  8. Thread.currentThread().sleep(100000);

  9. return "sleep on";

  10. } else {

  11. return sleep;

  12. }

  13. }

 

驗證方法:分別發送兩個請求,

第一個請求:http://localhost:8080/coreplat/sleepdata.do?sleep=on

第二個請求:http://localhost:8080/coreplat/sleepdata.do?sleep=test

驗證結果:第一個請求發出去之後,本地服務器等待100s,而後返回結果」sleep on」,在本地服務器等待的者100s當中,發送第二個請求,直接返回結果」test」。說明之間的線程是不互相影響的。

相關文章
相關標籤/搜索