使用Spring MVC有一段時間了,之前一直使用Struts2,在struts2中action都是原型(prototype)的, 說是因爲線程安全問題,對於Spring MVC中bean默認都是(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”。說明之間的線程是不互相影響的。