你們都知道前臺表單數據向後臺傳遞的時候,調用的Action會實現ModelDriven接口。僞碼以下:html
VO僞碼:java
public class User { private String userName; private String password; //setter and getter //.... }
Action僞碼:
數據庫
public class UserAction implements ModelDriven { private User user = new User(); public String addUser() { //相應的業務邏輯 } @Override public Object getModel() { return user; } }
JSP僞碼:jsp
<form action="xxx/user-add.action" method="post"> username:<input type="text" name="username" /> password:<input type="text" name="password" /> <input type="submit" name="submit" value="添加" /> </form>
上面的代碼相信你們很是熟悉,可是你們知道Strusts是如何把表單的值填到VO中的?若是你確實沒法回答,那麼建議認真往下讀。ide
用過Struts的人必定都據說過值棧(後面還會專門介紹),ModelDriven背後的機制正是VlaueStack。JSP頁面上的username/password可以被直接賦給user對象,這證實user對象是ValueStack中的一個root對象。那麼,user對象是怎麼進入ValueStack的呢?答案就是ModelDrivenInterceptor,攔截器你們必定也據說過,在這個攔截器中,會判斷當前要調用的Action對象是否實現了ModelDriven接口,若是是,這調用getModel方法,並把返回值壓入ValueStack。post
ModelDrivenInterceptor的代碼:this
public class ModelDrivenInterceptor extends AbstractInterceptor { protected boolean refreshModelBeforeResult = false; public void setRefreshModelBeforeResult(boolean val) { this.refreshModelBeforeResult = val; } @Override public String intercept(ActionInvocation invocation) throws Exception { Object action = invocation.getAction(); if (action instanceof ModelDriven) { //判斷是否實現ModelDriver接口 ModelDriven modelDriven = (ModelDriven) action; ValueStack stack = invocation.getStack(); Object model = modelDriven.getModel(); if (model != null) { stack.push(model); //將Action中getModel()方法返回的對象壓入值棧 } //下面這句條件判斷有什麼做用呢,請繼續往下看 if (refreshModelBeforeResult) { invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model)); } } return invocation.invoke(); }
咱們經過一個例子來看下爲何要refreshModelBeforeResult。spa
Action僞碼:code
public class UserAction implements ModelDriven { private User user = new User(); public String viewUser() { //相應的業務邏輯 user = userService.viewUser(); //從數據庫取出數據封裝到user對象中 return "更新頁面"; } @Override public Object getModel() { return user; } }
JSP僞碼:orm
<form action="xxx/user-update.action" method="post"> username:<input type="text" name="username" value="<s:property value="username" />" /> password:<input type="text" name="password" value="<s:property value="username" />" /> <input type="submit" name="submit" value="更新" /> </form>
在更新操做錢,確定須要先獲取到數據,若是沒有if(refreshModelBeforeResult),user對象經過getModel()方法被壓入到ValueStack中,這時候,UserAction和ValueStack都指向同一個user對象,但緊接着,UserAction中的user被一個新的user對象覆蓋,這時候,UserAction和ValueStack再也不指向同一個user對象!ValueStack中還是舊的user對象,而UserAction中是最新的user對象,可是咱們知道,在jsp頁面訪問的都是ValueStack中的user對象,因此它的屬性都將是空的。
經過以上的分析,能夠猜想,經過if(refreshModelBeforeResult)最終要將最新的值壓入ValueStack。
相關源碼:
// Add the new model on the stack if (needsRefresh) { // Clear off the old model instance if (originalModel != null) { root.remove(originalModel); } if (newModel != null) { stack.push(newModel); } }
即將酒的model從ValueStack中移除,將新的model壓入ValueStack!