模型驱动:作用:将动作和模型隔开
ModelDriven拦截器:
情景: 有一个用来处理客户的 CustomerAction 类, 该动作类实现了 ModelDriven 接口. 
当用户触发CustomerAction 动作时, ModelDriven 拦截器将调用相关CustomerAction 对象的 getModel() 方法, 并把返回的模型(Customer实例)压入到 ValueStack 栈. 接下来 Parameters 拦截器将把表单字段映射到 ValueStack 栈的栈顶对象的各个属性中. 因为此时 ValueStack 栈的栈顶元素是刚被压入的模型(Product)对象, 所以该模型将被填充. 如果某个字段在模型里没有匹配的属性, Param 拦截器将尝试 ValueStack 栈中的下一个对象.
一个模型类必须有一个不带任何参数的构造器.
Struts2的模型驱动将对象放置到栈顶。
使用场景:使用ModelDriven进行回显
/**
  * 如果该Action实现了模型驱动的接口,此时需要通过getModel,
  * 将传递的Customer进行出来,返回对应Customer对象,将Customer对象赋给Action中属性customer
  *   * 模型驱动的宗旨就是将该对象压入栈顶,这样好处可以方便的页面获取值,而且可以支持表单的回显
  * */
 <!-- struts标签支持回显,在标签中用name的属性值匹配对象栈中对应属性,这样的话就可以将对象栈中该属性对应的值,回显到对应的标签中 -->
方法一:
对模型驱动中的对象赋值
this.customer.setUsername("张三");
this.customer.setPsw("123");
this.customer.setTel("13212121212");
方法二:
//实例化javabean对象(Customer),放置栈顶
Customer c = new Customer();
c.setUsername("李四");
c.setPsw("11111");
c.setTel("88888888888");

//this.customer = c;
//获取值栈
ValueStack valueStack = ActionContext.getContext().getValueStack();  
//删除栈顶的对象
valueStack.pop();
//放入新的对象到栈顶
valueStack.push(c);
token防止表单重复提交:
<s:token />标签防止重复提交,用法如下:
第一步:在表单中加入<s:token />
<s:form action="helloworld_other" method="post" namespace="/test">
  <s:textfield name="person.name"/><s:token/><s:submit/>
  </s:form>
第二步:
<action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
         <interceptor-ref name="defaultStack"/>
          <!-- 增加令牌拦截器 -->
          <interceptor-ref name="token">
                  <!-- 哪些方法被令牌拦截器拦截 -->
                  <param name=“includeMethods">save</param>
          </interceptor-ref>    
         <!-- 当表单重复提交转向的页面 -->
        <result name="invalid.token">/WEB-INF/page/message.jsp</result>   
</action>
第三步:
     在message.jsp提示表单提示的错误信息,使用<s:actionerror>
以上配置加入了“token”拦截器和“invalid.token”结果,因为“token”拦截器在会话的token与请求的token不一致时,将会直接返回“invalid.token”结果。