標籤:
以UserAction為例,當UserAction實現了ModelDriven介面之後,與該介面相關的預設配置的攔截器會在攔截請求之後判斷該請求是將要被UserAction處理而且UserAction實現了ModelDriven介面,因此就會在執行UserAction的相應方法之前,調用getModel方法,將UserAction中的Model類(比如Use)r的對象(假設為u)壓入ValueStack中,作為root對象。這時候如果提交的表單或者url中傳值過來,比如username,password等,會直接賦值給u中的屬性(達到了將屬性儲存區在對象中,避免了在Controller中書寫大量屬性和getset方法,同時也避免了在傳值的時候書寫大量的u.XXXX,u.XXX造成理解困難和不直觀)。
在S:debug顯示的頁面中,可以看到,此時一個User類在棧頂,屬性為username和password(其值可以通過表單提交和url傳遞),棧頂下面是UserAction類,屬性為u和model兩個對User對象的引用,此時指向的是棧頂root中的User對象-----①。
然而,如果UserAction中對應--該請求的方法在getModel之後再將u指向另外一個User對象(UserAction中的model屬性和u同時指向新對象,可以理解為如果之後再執行getModel方法,那麼這個model指向的對象那個將被壓入),那麼這個對象不會被壓入ValueStack,不會作為root對象,因此其屬性不會被當做root對象屬性,被不加#的直接取到viewer頁面中。
此時,在view頁面中,取u.username,卻可以取到新對象的值,能取到值不難理解,但是為什麼u現在不在root中,前面不用#就可以取到呢?原因是u.username在棧頂裡面找不到,會在接下來裡面找,找到之後就返回。
假設UserAction在被調用getModel方法之後,執行的方法中不是將u賦與一個新對象,而是用u.setUsername方法呢?那麼因為①的原因,此時u指向的還是root對象,所以可以改變root中username的值的。達到更新的目的。
ModelDrivenInterceptor的原始碼中可以看到有個refreshModelBeforeResult屬性為false,如果設為true,則會在UserAction的方法調用之後,再調用一次getModel,如果此時u的指向有所改變,那麼會把u新指向的對象壓入棧中,達到更新的目的。
Struts2 的ModelDriven理解