所谓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中!