所謂ModelDriven,意思是直接把實體類當成頁面數據的收集對象,例如DepartmentAction。
假如要寫一個Action,我們可以有三種方式:1. 直接在Action中定義所有需要的屬性,然後再JSP頁面中直接用屬性名稱來提交數據。
壞處: 如果實體類的屬性多,Action中也要定義相同的屬性。
2. 直接在Action中定義Department對象,並添加Get和Set方法,然後再Jsp頁面中通過對象.屬性的方式來給對象賦值。
壞處: Jsp頁面上表單域中的命名太長,代碼不 簡潔
3. 利用ModelDriven機制,讓DepartmentAction實現一個ModelDriven接口,同時實現接口中的方法,getModel()。這種方式相對於來說是比較好的,Action和JSP寫起來都非常簡單。 下面主要介紹 ModelDriven的機制原理:
【Struts2中ModelDriven使用】
Struts2中獲取表單數據有兩種方式:Field-Driven(屬性驅動)Action和Model-Driven(模型驅動)。屬性驅動使用Action的屬性元素封裝請求參數,而模型驅動是使用javaBean來封裝來回請求參數。我們可以根據Action屬性的不同將它分爲兩類:Field-Driven(屬性驅動)Action和Model-Driven(模型驅動)Action。
1. Field-Driven(屬性驅動)Action,Action擁有自己的屬性,表單字段直接和Action的屬性對應。
2. 實現ModelDriven接口可以在action中直接獲得例如User對象,它會將Object getModel()取得的User放到ValueStack中。 可以理解爲將這個User對象的屬性追加到了Action中。
使用ModelDriven接口需要實現一個方法getModel():
public class BaseAction<T> extends ActionSupport implements ModelDriven<T>{
private Class classt;
private T t;
public BaseAction(){
try {
ParameterizedType type = (ParameterizedType) this.getClass()
.getGenericSuperclass();
this.classt = (Class) type.getActualTypeArguments()[0];
this.t = (T) this.classt.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public static final String LISTACTION="listaction";
public static final String ADDUI="addUI";
public static final String UPDATEUI="updateUI";
public static final String ACTION2ACTION="action2action";
@Override
public T getModel() {
return this.t;
}
}
該方法返回一個用於接收用於輸入數據的模型。在頁面中,這個模型的對象中的屬性可以直接通過屬性名來訪問,而不需要使用對象.屬性來訪問。在action中也不需要添加對象的get和set方法,但是必須要在Action中進行new操作,ModelDriven使用泛型。
【Struts2中模型驅動原理】
ModelDriven的實現主要是通過ModelDrivenInterceptor攔截器,該攔截器主要做的事就是調用Acton的getModel()方法,然後把返回的model壓入值棧。所以我們在jsp頁面中,直接通過對象的屬性名就能直接賦值給對象。說明了,此時對象正是ValueStace中的一個root對象。
下面是ModelDrivenInterceptor的代碼:
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) {
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
if (refreshModelBeforeResult) {
invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();
}
從ModelDrivenIntercptor中,即可以看到model對象被壓入ValueStack中!