1.前提知識
1)scope預設值
進行SSH整合開發時,Struts2的action須要用spring容器進行管理,僅僅要涉及到類以bean的形式入到spring容器中。無論是xml配置還是使用註解方式進行配置,都會涉及到spring管理bean的scope。其一共同擁有五種取值,而其預設值為singleton。也就是單例模型,全部對此bean引用為同一個物件。
2)action應為多例
struts2作為MVC中檢視(View)層框架,其最主要任務就是接收使用者請求。然後呼叫業務邏輯層進行處理,這樣的特徵也就是意味著每一個HTTP請求都必須相應一個單獨的action,不然會出現資料衝突。
3)那麼問題來了
通過上述兩點能夠看出兩者是矛盾的,所以當spring須要管理action時,就必須更改其scope為prototype。而不是使用其預設值-singleton。
2.錯誤現象
進行使用者加入時,假設spring管理action的方式為預設值(singleton)就會造成加入完使用者後,當進行再次加入時發現資料進行自己主動回顯(前提使用了struts2標籤而且使用了ModelDriven),無論是關閉瀏覽器還是換其他瀏覽器都是如此,使用<s:debug>標籤呼叫時,發現值棧的root棧的棧頂就是之前加入的使用者(model)。
3.原因分析
1)spring容器啟動
spring容器啟動時。會建立加入使用者action的例項,由於其scope為singleton方式,所以以後每次請求此action都會呼叫同一個action物件,由此也埋下了滅亡的種子。
2)經過modelDriven攔截器
使用者在輸入完資訊,點選提交。
由於加入使用者須要對錶單輸入資料進行封裝。此時採用了封裝資料最標準的做法實現ModelDriven介面,那麼當請求加入的action時,會經過modelDriven攔截器,此攔截器通過getModel方法獲取目標model然後push到valuestack的棧頂;
2)經過param攔截器
當經過攔截器params時,其會對棧頂的model進行賦值。
3)執行action
執行加入action進行加入操作。而且完畢興許。
4)再次請求加入action轉發
此時又從spring容器中取出加入的action,因為其scope為singleton,所以此action與之前的action為同一個,而此前加入的還儲存在action中。
5)再次經過modelDriven攔截器
再次經過攔截器modelDriven,此時action中的model再次被放到valuestack的棧頂,再次提醒model中是有值的。
6)到達介面
到達介面時,就會依據model中值進行回顯。