ScopedModelDrivenInterceptor 該攔截器處於defaultStack第八的位置,其主要功能是從指定的作用域內檢索相應的model設置到Action中,該類中有三個相關的屬性: scope:從哪裡獲取model,有兩個值,一是request,二是session,默認值為request name:在scope中檢索model的key className:model類的名稱,也就是該model是什麼類型 雖然這三個參數都可以進行設置,但是在defaultStack中struts2並沒有為其賦值,所以初始值這三個屬性都為null。 下面我們去看一個ScopedModelDriven接口,該接口繼承自ModelDriven接口,實現了ScopedModelDriven接口也就實現了ModelDriven,所以當前Action也會有ModelDriven的特性,ModelDriven在下一個攔截器中介紹。ScopedModelDriven接口中相當於有四個方法: 1.getModel() -->用於Action獲取model 2.setModel() -->提供給ScopedModelDrivenInterceptor為Action設置model 3.getScopeKey() -->用於Action獲取model存儲在作用域中的key,這裡對應了ScopedModelDrivenInterceptor中的name屬性 4.setScopeKey() -->提供給ScopedModelDrivenInterceptor為Action設置model存儲的key 下面是ScopedModelDrivenInterceptor的intercept方法源碼: [java] @Override public String intercept(ActionInvocation invocation) throws Exception { Object action = invocation.getAction();//獲取當前正在執行的Action //如果Action實現了ScopedModelDriven接口 if (action instanceof ScopedModelDriven) { ScopedModelDriven modelDriven = (ScopedModelDriven) action;//強轉 if (modelDriven.getModel() == null) {//如果返回為null,如果不為null的話是不會去修改該Action中model屬性的 ActionContext ctx = ActionContext.getContext();//獲取ActionContext ActionConfig config = invocation.getProxy().getConfig();//獲取Action配置 //model類名,初始值為null String cName = className; if (cName == null) { try { Method method = action.getClass().getMethod(GET_MODEL, EMPTY_CLASS_ARRAY);//通過反射獲取getModel方法 Class cls = method.getReturnType();//獲取getModel方法的返回值類型 cName = cls.getName();//獲取model類名 } catch (NoSuchMethodException e) {//如果沒有getModel方法則拋異常 throw new XWorkException("The " + GET_MODEL + "() is not defined in action " + action.getClass() + "", config); } } String modelName = name;//model存儲的key,初始值為null if (modelName == null) { modelName = cName;//把model的類名賦給model存儲的key } Object model = resolveModel(objectFactory, ctx, cName, scope, modelName);//解析model modelDriven.setModel(model);//把返回的model對象設置到Action中 modelDriven.setScopeKey(modelName);//返回model存儲的key設置到Action中 } } return invocation.invoke();//調用下一個攔截器 } 該方法的邏輯還是挺簡單的,如果Action的getModel方法返回不為null的話,strust2就不會去修改Action的model屬性,這也更符合我們的應用 要求,不然這個攔截器就太"霸道"了,然後去解析獲取model對象,最後把返回的model對象與model對象存儲的key設置到Action中,現在去看一下 resolveModel方法: [java] protected Object resolveModel(ObjectFactory factory, ActionContext actionContext, String modelClassName, String modelScope, String modelName) throws Exception { Object model = null; Map<String, Object> scopeMap = actionContext.getContextMap();//獲取ActionContext內容的context Map對象 if ("session".equals(modelScope)) {//如果配置了scope為session,但這裡並沒有配置 scopeMap = actionContext.getSession();//所以這裡不會執行 } model = scopeMap.get(modelName);//去context Map(即相當於request作用域)中查找 if (model == null) {//沒有找到 model = factory.buildBean(modelClassName, null);//調用對象工廠的buildBean方法實例化一個對象 scopeMap.put(modelName, model);//放置到context Map中 } return model;//返回model對象 } 該方法先去作用域查找,如果查找不到再由ObjectFactory對象創建一個,ObjectFactory是struts2中專門用於創建對象的,其內部就是通過反射調用 class.newInstance()創建,sturst2中的Action、Result、Interceptor都是由ObjectFactory創建。model對象創建好後放入到了request作用域中,該方法執行完成後又把返回的model設置進了Action,如果Action對model進行了接收,那麼Action中的model是有值的。