最近發現使用了springMVC的新項目偶爾出現connection closed,同事反映當訪問同一個controller時經常出現類似錯誤
上回發現在使用
<context:component-scan base-package="com.controller" /> |
對@controller註解掃描生成的controller,若是沒有加@Scope("prototype")的話,生成出來的controller就是單例的。見http://blog.chinaunix.net/uid-11121450-id-3258548.html
雖然發現這個問題但是由於connection closed的錯誤現象很難重現,因此上回放棄了。
今天晚上我在測試中無意中又出現了這樣的錯誤,我對controller加了@Scope("prototype"),還是出現一樣的錯誤。
我用下面的語句打印本類的地址,發現每次打印出來的地址都不一樣,證明每次請求都重新創建了controller
System.out.println("reserve:"+this.getClass().getName() +"@"+Integer.toHexString(this.hashCode())); |
這時我注意到service是用@Autowired,於是我把service的地址也打印出來,發現service 的地址,每次訪問都是一樣的。也就是說雖然controller是多例了,但是裏面的service是單例的,因此每次把新建的connection賦予service之後,請求結束就關閉連接這種方式存在問題。
我的每一個service的connection是通過setConn訪問給傳進去的,其它數據庫方法都使用這個service的connection.
在兩個請求同時請求到同一個service時,若是先開始創建connection一個service執行比較慢,而另一個後開始的service也申請了新的一個connection,由於service是單例的,就會把第一個connection給覆蓋掉了。若是第二個service先完成就關閉連接,那麼第一個service就會出現“connection closed”錯誤,從而出現一個未關閉的connection(第一個service申請的connection)。
解決辦法
1.在controller和service上都增加@Scope("prototype"),這樣controller和service都是多例。
2.service不採取setconn方法,每個方法都從參數獲取connection.