zoukankan      html  css  js  c++  java
  • 模型驱动 ModelDriven

    转载自:https://www.cnblogs.com/lxboy2009/p/6105605.html

    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中的信息

      }

    }

    合群是堕落的开始 优秀的开始是孤行
  • 相关阅读:
    获取指定日期相关DATENAME和DATEPART数据
    MySQL 5.7 新备份工具mysqlpump 使用说明
    Kubernetes之Pod控制器
    Python3出现"No module named 'MySQLdb'"问题-以及使用PyMySQL连接数据库
    分布式监控系统Zabbix3.4-针对MongoDB性能监控操作笔记
    基于MongodbDB的用户认证-运维笔记
    基于Nginx+Keepalived的LB服务监控(邮件报警)
    Linux系统用户密码规则
    通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记
    Centos6.9下RocketMQ3.4.6高可用集群部署记录(双主双从+Nameserver+Console)
  • 原文地址:https://www.cnblogs.com/biaogejiushibiao/p/9496116.html
Copyright © 2011-2022 走看看