在struts2中提供了一种特殊的领域对象的访问方式ModelDriven,我们可以通过ModelDriven直接操作应用程序中的模型对象,我们可以再不同层中使用相同的对象。使用ModelDriven必须要在action中实现com.opensymphony. xwork2.ModelDriven接口,在这个接口中有一个getModel()方法,这个方法返回一个用于接收用户输入数据的模型对象。下面是一个简单的应用ModelDrivenDemo,通过这个例子我们分析模型驱动的原理以及好处。

   在这个例子中ModelDriven中采用了泛型的方式:

<span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">public</span> <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">abstract</span> <span class="hljs-class" style="border: 0px; margin: 0px; padding: 0px; font-weight: bold; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(68, 85, 136); background: transparent;"><span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">class</span> <span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;">BaseAction</span><<span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;">T</span>> <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">extends</span> <span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;">ActionSupport</span> <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">implements</span> <span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;">ModelDriven</span><<span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;">T</span>> </span>{
 
    <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">protected</span> T model;
    <span class="hljs-function" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;"><span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">public</span> T <span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(25, 70, 157); background: transparent;">getModel</span><span class="hljs-params" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(0, 0, 255); background: transparent;">()</span> </span>{
        <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">return</span> model;
    }
}

        这样我们才RoleAction中传递参数为Role,在UserAction中传递参数为User。

   在action中我们可以直接应用model:

<span class="hljs-javadoc" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: italic; font-family: inherit; vertical-align: baseline; color: rgb(64, 128, 128); background: transparent;">/** 添加 */</span>
<span class="hljs-function" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;"><span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">public</span> String <span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(25, 70, 157); background: transparent;">add</span><span class="hljs-params" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(0, 0, 255); background: transparent;">()</span> <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">throws</span> Exception </span>{
 
     roleService.save(model);
 
     <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">return</span> <span class="hljs-string" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(33, 145, 97); background: transparent;">"toList"</span>;
}

        或者利用model获取实体中的属性:

<span class="hljs-javadoc" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: italic; font-family: inherit; vertical-align: baseline; color: rgb(64, 128, 128); background: transparent;">/** 修改页面 */</span>
<span class="hljs-function" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;"><span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">public</span> String <span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(25, 70, 157); background: transparent;">editUI</span><span class="hljs-params" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(0, 0, 255); background: transparent;">()</span> <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">throws</span> Exception </span>{
     <span class="hljs-comment" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: italic; font-family: inherit; vertical-align: baseline; color: rgb(64, 128, 128); background: transparent;">// 准备回显的数据</span>
     Role role = roleService.getById(model.getId());
     ActionContext.getContext().getValueStack().push(role);
 
     <span class="hljs-keyword" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(149, 65, 33); background: transparent;">return</span> <span class="hljs-string" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(33, 145, 97); background: transparent;">"saveUI"</span>;
}

       我们同样也可以在web层面使用model,这样我们在用实体属性的时候只需要使用属性即可,不用再用实体.属性:

<tr>
<td>用户名:</td>  
<td><input type=<span class="hljs-string" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(33, 145, 97); background: transparent;">"text"</span> name=<span class="hljs-string" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(33, 145, 97); background: transparent;">"username"</span>></td>  
</tr>  
<tr>  
<td>密码:</td>  
<td><input type=<span class="hljs-string" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(33, 145, 97); background: transparent;">"password"</span> name=<span class="hljs-string" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(33, 145, 97); background: transparent;">"password"</span>></td>  
</tr>

(如果不使用modeldriven,红色部分就应该写好具体的实体.属性,例如user.name,user.password)

    以上就是应用ModelDriven的地方,在实际的编程中确实给我们带来了很多方便,在Action中,我们采用model封装了实体,就不在需要为某个对象提供getter和setter方法,避免了,如果实体属性过多,会导致action中代码冗余,在页面中我们访问对象,不在需要实体.属性来表示,只需要直接写属性即可。

    下面我们分析ModelDriven机制的原理,为什么会允许我们在不同的层中可以用相同的对象,为什么可以直接使用属性就可以使用对应的实体。

    下面这个图是struts2的执行过程:

        在这个图里我们可以看到,在一个请求发出之后,经过action之前会进行拦截,在struts2的默认配置文件中对于拦截器是这样的:

<span class="hljs-tag" style="border: 0px; margin: 0px; padding: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; color: rgb(0, 0, 128); background: transparent;"><<span class="hljs-title" style="border: 0px; margin: 0px; padding: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; background: transparent;">interceptors</span>></span>
       ……
       <span class="hljs-comment" style="border: 0px; margin: 0px; padding: 0px; font-weight: inherit; font-style: italic; font-family: inherit; vertical-align: baseline; color: rgb(64, 128, 128); background: transparent;"><!--定义属性驱动的拦截器—>
       <interceptor name=”params” class=”com.opensymphony.xwork2.interceptor.ParametersInterceptor” />
       <!--定义模型驱动的拦截器—>
<interceptor name=”model-driven”  class=”com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor” />
       ……
       <!--定义模型驱动的拦截器栈—>
       <interceptor-stack name=”modelDrivenStack”>
              <interceptor-ref name=”model-driven”/>
              <interceptor-ref name=”basicStack”/>
       </interceptor-stack>
……
       <interceptor-stack name=”defaultStack”>
              <interceptor-ref name=”model-driven”/>
              <interceptor-ref name=”params”/>
       </interceptor-stack>
</interceptors>
<!--定义Struts2默认的拦截器栈—>
<default-interceptor-ref name=”defaultStack” />
</span>

        从上面的配置中我们可以看到拦截器栈采用的就是ModelDrivenStack,其中params拦截器负责提取请求的参数,如果是使用的属性驱动模式,它还负责将请求参数传给Action实例的属性;而model-driven拦截器则负责把请求参数传给模型的属性。当程序采用getModel()取得结果之后,会把结果放到ValueStack值栈中,Model对象一直处于栈顶的位置,所有从页面提交过来的参数都可以被model接收,也即被model封装,所以我们可以再页面中进行对model的访问, 实现了不同层之间访问相同的对象。

本文转载自 肖红 廊坊师范学院信息技术提高班 第十期 , 原文链接:Struts2的ModelDriven机制 , 转载请保留本声明!