ModelDriven:模型驱动,对所有action的模型对象进行批处理.

我们在开发中, 在action中一般是用实体对象,然后给实体对象get,set方法。

RegAction{
  User user ;
  //get/set
}

然后在jsp页面中给action中的user属性绑定值是通过如下方式

<s:textfield name="user.name" />
<s:textfield name="user.age" />
<s:textfield name="user.birthday" />

这样都要加上user.因为在值栈中action进入值栈的时候,值栈中存储的值就是以user.name这种形式存在的,所以ognl搜索值栈的时候,也要按这个名字来搜索。

这样就 比较麻烦,于是就引入了模型驱动。

引入模型驱动后在jsp页面绑定属性值的时候就可以不用加上user.  如:

<s:textfield name="name" />
<s:textfield name="age" />
<s:textfield name="birthday" />

原理是什么:ognl在搜索name值的时候,会把模型驱动user压入栈顶。ognl在值栈扫描的时候,会从上往下找,这样就会搜到user中的name,等等

是模型拦截器把模型压入栈顶的。

<html>
    <head>
        <title>reg.jsp</title>
    </head>
    <body>
        <s:actionerror/>
        <s:form namespace="/md" action="MdAction_reg" method="post" theme="xhtml" validate="true">
            <s:textfield name="name" label="UserName" />
            <s:textfield name="age" label="UserAge" />
            <s:submit />
        </s:form>
    </body>
</html>

user类

public class User {
    private Integer id ;
    private String name ;
    private Integer age ;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    public String toString() {
        return "User("+id+","+name + ","+ age + ")";
    }
}
/**
 * MdAction:某型驱动
 */
public class MdAction extends ActionSupport implements ModelDriven<User>,Preparable {
private String name;
由于使用了模型驱动,user处于栈顶,
user中也有name,那么jsp页面绑定的name是user中name,并不是这里的name,所以该name值为null,
同理在修改功能传id的时候,如果user中有id属性,而在action中也定义了一个id来接收该参数,这样id也接收不到值
,因为使用了模型驱动后,模型驱动拦截器会把id的值传给user中的id,而不是action中的id属性,为了解决这个问题,需要把action中接收参数id的属性定义为别的名称。
比如uid,同时修改jsp中的传参为uid,这样就解决了这个问题。这是在使用模型驱动的时候需要注意的地方。

private User user = new User();属性user,模型驱动栈顶的对象

public String reg() { return "success"; } @SkipValidation public String toRegView() { System.out.println("toRegView"); return "regView"; } public User getModel() { return user; } public String getName() { return name; } public void setName(String name) { this.name = name; }

public User getModel() {
          return user;//这里返回的就是action中的属性user,如果在action中的其他方法里,使用了User user=new User(),那么这个user对象就不是模型驱动的的对象,

也就是不处在栈顶。即使把当前new出的user赋值给属性user也不行,因为在值栈中是通过引用来实现,即值栈中是对象的地址。
      }

public String Edit()

    {

    User u = new User();

    u.setId(uid);

    u.setName("jerry");
    u.setAge(30);
    user = u ;注意,这里的user并不是栈顶的user,引用已经指向了新对象u

    如果要把u对象放到栈顶,可以手动的push

    ServletActionContext.getContext().getValueStack().push(u) ;//把u对象放到栈顶,那么执行修改时回显的就是该对象的数据。

   }

}

上面的方法是手动把u对象压入栈顶,还有一种方法可以解决这个问题。

模型驱动拦截器的高级应用:

struts在调用模型驱动拦截器的之前会调用prepare拦截器,prepare拦截器中会调用一个prepare方法,该方法在模型驱动拦截器之前调用,也就是在模型驱动

拦截器中的getModel方法之前执行,getModel方法返回的就是栈顶的对象,那么可以在prepare中把getModel方法中要返回到栈顶的对象给换掉,也就是重新引用。

这样就不用手动的push到栈顶了。

/**
 * MdAction:某型驱动
 */
public class MdAction extends ActionSupport implements ModelDriven<User>,Preparable {
    private static final long serialVersionUID = -6933309304624396640L;

    private String name;

    private Integer uid ;

    private User user = new User();//模型驱动的getModel方法返回到栈顶的对象。user

    private List<User> userList ;

    public String reg() {
        return "success";
    }

    @SkipValidation
    public String toRegView() {
        System.out.println("toRegView");
        return "regView";
    }

    /**
     * 查询所有用户
     */
    public String findAllUsers(){
        userList = new ArrayList<User>();
        User u = null ;
        for(int i= 0 ; i < 10 ; i ++){
            u = new User();
            u.setId(1 + i);
            u.setName("tom" + i);
            u.setAge(20 + i);
            userList.add(u);
        }
        return "userListView";
    }

    public String edit(){
        return "editView" ;
    }

    //
    public User getModel() {
        return user;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    /**
     * 该方法在getModel之前运行,在modelDriven拦截器之前先运行
     */
    public void prepareEdit() throws Exception { 该命名规则说明在执行Edit的时候才会执行该方法。
        //
        User u = new User();
        u.setId(uid);
        u.setName("jerry");
        u.setAge(30);
        user = u ;把user对象换掉,换成新new出的对象。
    }

    public void prepare() throws Exception {
    }
}

但是由于使用的是默认拦截器栈,prepare拦截器在params拦截器之前执行,这样在编辑的时候,就无法获取到id值,因为此时还没有经过参数params烂机器的处理。

所以这种方法不能使用默认的拦截器栈,struts-default.xml提供了一个拦截器栈paramsPrepareParamsStack,所以要引入该拦截器栈。

<struts>
    <package name="MdPkg" namespace="/md" extends="struts-default">
        <action name="MdAction_*" class="struts2.modeldriven.MdAction" method="{1}">
            <result name="success">/md/reg.jsp</result>
            <result name="regView">/md/reg.jsp</result>
            <result name="editView">/md/edit.jsp</result>
            <result name="userListView">/md/userList.jsp</result>
            <interceptor-ref name="paramsPrepareParamsStack" /> 不能引入默认拦截器栈,要在prepare拦截器之前执行params拦截器
        </action>
    </package>
</struts>

模型驱动的应用:

假设在开发中有很多实体对象,比如用户类User,订单类Order,部门类Department等等

对应的有很多Action,如UserAction,OrderAction,DepartmentAction等等。

UserAction{

  User user;

}

OrderAction{

  Order order;

}

如果在开发中需要开发一个处理模型的拦截器

ProcessModelInterceptor{

  if(action instanceof(UserAction){

    Object o=getUser();//得到该实体类的对象

  }

else if(action instanceof(OrderAction){

    Order o=getOrder();//得到该实体类的对象

  }

....

这样如果有很多的类几十甚至上百个实体类,都要这么去判断,将是十分的麻烦。引入了模型驱动后就解决了这个问题。

}

引入模型驱动后的做法:模型驱动的好处是对所以的action模型对象进行批处理

ProcessModelInterceptor{

  if(action instanceof(ModelDriven){//判断action是否实现了模型驱动接口

    Object o=((ModelDriven)action).getModel();//得到action的模型对象

    然后用反射获取action中的信息

  }

}

模型驱动 ModelDriven的更多相关文章

  1. Struts2中ModelDriven的使用

    它是Struts2种独有的一种接收用户输入的机制,想在项目中使用模型驱动 (ModelDriven)需要让Action实现com.opensymphony.xwork2.ModelDriven 接口, ...

  2. Struts2基础-4-2 -struts拦截器实现权限控制案例+ 模型驱动处理请求参数 + Action方法动态调用

    1.新建项目,添加jar包到WEB-INF目录下的lib文件夹,并添加到builde path里面 整体目录结构如下 2.新建web.xml,添加struts2核心过滤器,和默认首页 <?xml ...

  3. Struts2 入门

    一.Struts2入门案例 ①引入jar包 ②在src下创建struts.xml配置文件 <?xml version="1.0" encoding="UTF-8&q ...

  4. 初识Struts2

    一.Struts2入门案例 ①引入jar包 ②在src下创建struts.xml配置文件 <?xml version="1.0" encoding="UTF-8&q ...

  5. Action接收页面传来的参数方法

    接收页面传来的参数方法 1.第一种:在action中设置相应的变量 在相应的action中设置与将要传进来的参数名相同的变量 eg: 页面传给后台两个参数 name=chance & age ...

  6. (二)Struts2 核心知识

    所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:Struts2 get/set 自动获取/设置数据 action代码: ...

  7. 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具

        Java学习路线图引言:        黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...

  8. Java自学开发编程路线图(文中有资源福利)

    Java 语言入门 免费视频资源<毕向东Java基础教程>:http://yun.itheima.com/course/7.html JavaEE 学习大纲 所处阶段 主讲内容 技术要点 ...

  9. [ SSH框架 ] Struts2框架学习之二

    一.Struts2访问Servlet的API 前面已经对 Struts2的流程已经执行完成了,但是如果表单中有参数如何进行接收又或者我们需要向页面保存一些数据,又要如何完成呢?我们可以通过学习 Str ...

随机推荐

  1. 《Intel汇编第5版》 汇编拷贝字符串

    一.字符串定义 二.dup指令 三.调用Writestring过程 四.代码以及效果 TITLE String Copy INCLUDE Irvine32.inc includelib Irvine3 ...

  2. DMI ( Dynamic Method Invocation )

    功能: 点击 hello , 调用 execute 函数 点击 update , 调用 update 函数 1.项目结构 2.web.xml <?xml version="1.0&qu ...

  3. JavaScript——Cookie

    JavaScript中的Cookie基础 页面用来保存信息的,比如登录.记住用户名. [cookie的特性] (1)同一个网站中所有页面共享一套cookie: (2)数量.大小有限: (3)有保质期, ...

  4. 更新sdk

    更新sdk,遇到了更新下载失败问题: Fetching https://dl-ssl.google.com/android/repository/addons_list-2.xmlFetched Ad ...

  5. redis安装以及远程连接

    第一步下载: Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. 第二步: 运行安装 记录安装路径 C:\Program Fil ...

  6. 快捷高效的cmd命令

    经常在网上逛一些博客看一些技术文章,但是每每看过之后又忘记保存,或者东存一下,西存一下,到需要的时候回过头来,往往都找不到了.所以开通这个博客,把看到的好东西都记录下来,以便回头查看,也能与大家分享分 ...

  7. Windows下WordPress搭建博客过程

    搭建环境:Win7 + XAMPP5.5 + wordpress4.5.1 官网下载安装包,解压,拷贝到网站根目录(D:\IT\XAMPP5.5\htdocs\),重命名为blog(随意) 创建数据库 ...

  8. JS 阻止整个网页的内容被选中

    pretty-girl { -webkit-user-select: none; } 可是!可是!不是每个浏览器都可以不忧桑!!!那就只能请脚本大王出山了. 阻止选中 有时候,我们需要禁止用户选中一些 ...

  9. Oracle 四种列转行的方法

    1. Oracle自带列转行函数listagg: 实例: with temp as( select 'China' nation ,'Guangzhou' city from dual union a ...

  10. 一个简单的jQuery插件开发实例

    两年前写的一个简单的jQuery插件开发实例,还是可以看看的: <script type="text/javascript" src="jquery-1.7.2.m ...