ModelDrivenInterceptor 該攔截器處於defaultStack中的第九的位置,在ScopedModelDrivenInterceptor攔截器之後,要使該攔截器有效的話,Action必須實現ModelDriven接口,該接口就一個方法:getModel(),ModelDrivenInterceptor攔截器主要做的事就是調用Action的getModel()方法然後把返回的model壓入值棧(如果不為null)。如果Action實現了ScopedModelDriven接口也就實現了ModelDriven接口,因為ScopedModelDrivenInterceptor在執行的過程肯定會返回一個model對象再調用Action的setModel(model)方法,如果Action對model進行了接收,那麼在執行到ModelDrivenInterceptor攔截器的時候,Action的getModel()方法返回的就是ScopedModelDrivenInterceptor攔截器設置進去的值,已經不為null了,所以該model自然就會壓入值棧。下面是該攔截器intercept方法源碼: [java] @Override public String intercept(ActionInvocation invocation) throws Exception { Object action = invocation.getAction();//獲取當前正在執行的Action //如果Action實現了ModelDriven接口 if (action instanceof ModelDriven) { ModelDriven modelDriven = (ModelDriven) action; ValueStack stack = invocation.getStack(); Object model = modelDriven.getModel();//通過getModel方法獲取model if (model != null) {//如果model不為null則把model壓入值棧 stack.push(model); } if (refreshModelBeforeResult) {//在執行Result之前是否要更新model對象,默認為false invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model)); } } return invocation.invoke();//調用下一個攔截器 } 該方法邏輯很簡單,正如前所說的一樣,就是把getModel方法返回的結果壓入值棧而已,我們一般實現這個接口是利用壓入值棧的model對象接收從頁面提交過來的數據,有很多時候我們是在Action中寫屬性來接收參數的,因為Action也是在值棧中,而struts2在賦值參數的時候是在值棧從棧頂往棧底尋找有相應setter方法的對象,而這時model壓入了值棧,它是處於棧頂的,所以從頁面提交過來的參數也就被model對象接收了。這種方式呢model對象有點像struts1.X裡面formbean對象的功能。 ModelDrivenInterceptor攔截器中還有個名為refreshModelBeforeResult的屬性,用於設置在執行Result之前是否要更新model對象,默認值是false也就不會去更新,我們有可能在Action的執行過程將model這個引用變量指向了另外一個對象,如果你把refreshModelBeforeResult設置了為true,那麼在Result執行之前PreResultListener就會用這個新的對象將值棧中的對象替換,達到更新效果。 PreResultListener是一種監聽器由ActionInvocation對象進行注冊,在Result執行之前會執行該種監聽器的beforeResult方法。雖然在defaultStack中,struts2是不會在ActionInvocation中注冊這個RefreshModelBeforeResult監聽器的,我們還是去簡單看一下: [java] protected static class RefreshModelBeforeResult implements PreResultListener { private Object originalModel = null; protected ModelDriven action; public RefreshModelBeforeResult(ModelDriven action, Object model) { this.originalModel = model; this.action = action; } public void beforeResult(ActionInvocation invocation, String resultCode) { ValueStack stack = invocation.getStack();//獲取值棧 CompoundRoot root = stack.getRoot();//獲取值棧的root對象 boolean needsRefresh = true; Object newModel = action.getModel();//從Action中獲取新的model對象 // Check to see if the new model instance is already on the stack for (Object item : root) { if (item.equals(newModel)) {//如果新的model對象與舊的相同則不刷新 needsRefresh = false; } } // Add the new model on the stack if (needsRefresh) {//如果要刷新 // Clear off the old model instance if (originalModel != null) { root.remove(originalModel);//先移除舊model } if (newModel != null) { stack.push(newModel);//將新model對象壓入值棧 } } } } RefreshModelBeforeResult實現了PreResultListener接口,是ModelDrivenInterceptor的一個靜態內部類,在執行Result之前執行其beforeResult方法 如何進行刷新的很簡單相信大家都看得懂。