1. 程式人生 > >在springMvc的@controller層,單例模式下慎用成員變數

在springMvc的@controller層,單例模式下慎用成員變數

http://m.blog.csdn.net/article/details?id=40739619

CSDN部落格

spring MVC中的controller是單例模式,但是是多執行緒,各個執行緒之間不影響!

JAVA教程java基礎JAVA框架SpringSpring MVCStrutsStruts1Swing教程JAVA經驗JAVA面試多執行緒面試題常見JAVA面試題智力面試題

spring mvc Controller類預設Scope是單例(singleton)

By Lee - Last updated: 星期一二月 10, 2014 Leave a Comment

使用Spring MVC

有一段時間了,之前一直使用Struts2,struts2action都是原型(prototype)的, 說是因為執行緒安全問題,對於Spring MVCbean預設都是(singleton)單例的,那麼用@Controller註解標籤注入的Controller類是單例實現的?

測試結果發現spring3中的controller預設是單例的,若是某個controller中有一個私有的變數i,所有請求到同一個controller時,使用的i變數是共用的,即若是某個請求中修改了這個變數a,則,在別的請求中能夠讀到這個修改的內容。 若是在@Controller之前增加@Scope(prototype

),就可以改變單例模式為多例模式

以下是測試步驟,程式碼與結果.

1. 如果是單例型別類的,那麼在Controller類中的類變數應該是共享的,如果不共享,就說明Controller類不是單例。以下是測試程式碼:

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;

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

import org.springframework.web.bind.annotation.ResponseBody;

@Controller

public class ExampleAction {

    private int singletonInt=1;

     @RequestMapping(value = "/test")

     @ResponseBody

     public String singleton(HttpServletRequest request,

             HttpServletResponse response) throws Exception {

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

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

             try{

              int paramInt= Integer.parseInt(data);

             singletonInt = singletonInt + paramInt;

             }

             catch(Exception ex){

                 singletonInt+=10;

             }

         }else{

             singletonInt+=1000;

         }

         return String.valueOf(singletonInt);

    }

}

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

得到的返回結果如下。

第一次: singletonInt=15

第二次: singletonInt=30

第三次: singletonInt=45

從以上結果可以得知,singletonInt的狀態是共享的,因此Controller是單例的。

2. 如果Controller類是單例,那麼多個執行緒請求同一個Controller類中的同一個方法,執行緒是否會堵塞

@RequestMapping(value = "/sleepdata")

@ResponseBody

public String switcher(HttpServletRequest request

     , HttpServletResponse response)

           throws Exception {

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

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

      Thread.currentThread().sleep(100000);

       return "sleep on";

   } else {

       return sleep;

  }

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

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

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

驗證結果:第一個請求發出去以後,本地伺服器等待100s,然後返回結果”sleep on,在本地伺服器等待的者100s當中,傳送第二個請求,直接返回結果”test”。說明之間的執行緒是不互相影響的。