Struts2浅析 之 模型驱动与属性驱动

来源:互联网 发布:京东霹雳软件 编辑:程序博客网 时间:2024/06/01 07:37


1.Struts2的属性驱动.

Struts2的属性驱动指的是在action中JSP页面的每一个form中的name都对应在action中有一个属性与之对应。看下面代码片段:

<form action="register.do" name="RegisterForm" method="post">            Username:<input type="text" name="uname"><br>            Password:<input type="password" name="upass"><br>            Confirm: <input type="password" name="rpass"><br>            <input type="submit" value="Submit"></form>

这是一个最基本的用户注册的表单,它有三个数据要提交: uname、upass、rpass,那么对应的Action也要有三个属性(其实是三个属性的setter),看register.do实际的Action定义类:

package org.abu.csdn.action.user;import com.opensymphony.xwork2.ActionSupport;/** * Struts2属性驱动演示用的Action */public class RegisterAction extends ActionSupport {    private String uname;    private String upass;    private String rpass;    public String getUname() {        return uname;    }    public void setUname(String uname) {        this.uname = uname;    }    public String getUpass() {        return upass;    }    public void setUpass(String upass) {        this.upass = upass;    }    public String getRpass() {        return rpass;    }    public void setRpass(String rpass) {        this.rpass = rpass;    }       @Override    public String execute() throws Exception {               return ActionSupport.SUCCESS;    }}
你会看到RegisterAction中的三个属性和RegisterForm表单中的name属性名字一模一样,没错,这就是Struts2的属性驱动,当表单提交到RegisterAction后,Struts2将会自动将根据表单的name属性调用Action中相应的属性setter,去自动赋值。

2.Struts2的模型驱动

Struts2的模型驱动其实和Struts1.x中的ActionForm有点类似,在Struts1.x中每一个Action都必须有一个ActionForm与之对应,而Struts2.0中,每一个Action同样需要提供一个POJO对象,用来封装表单属性,看代码:

<form action="register.do" name="RegisterForm" method="post">            Username:<input type="text" name="uname"><br>            Password:<input type="password" name="upass"><br>            Confirm: <input type="password" name="rpass"><br>            <input type="submit" value="Submit"></form>
这段表单的代码和上面的一模一样,就不赘述了。接下来看POJO的代码,其实就是普通的Java Bean:
package org.abu.csdn.action.user;import com.opensymphony.xwork2.ActionSupport;/** * Struts2属性驱动演示用的Java Bean */public class User {    private String uname;    private String upass;    private String rpass;    public String getUname() {        return uname;    }    public void setUname(String uname) {        this.uname = uname;    }    public String getUpass() {        return upass;    }    public void setUpass(String upass) {        this.upass = upass;    }    public String getRpass() {        return rpass;    }    public void setRpass(String rpass) {        this.rpass = rpass;    }  }
也是和属性驱动中的例子一样,很简单,因为演示的都是同一个例子,只是方法不同而已,但是接下来就不一样了,看RegisterAction代码:

package org.abu.csdn.action.user;import org.abu.csdn.dto.User;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ModelDriven;/** * Struts2模型驱动演示用的Action * */public class RegisterAction extends ActionSupport implements ModelDriven<User> {    private User user;       public User getUser() {        return user;    }    public void setUser(User user) {        this.user = user;    }    @Override    public String execute() throws Exception {               return ActionSupport.SUCCESS;    }    // 模型驱动必须实现的方法,也是ModelDriven接口中唯一的方法    public User getModel() {               return user;    }}


和属性驱动的Action有很大的区别,下面一一列举:

(1)模型驱动的Action必须实现ModelDriven接口,而且要提供相应的泛型,这里当然就是具体使用的Java Bean了。

(2)实现ModelDriven的getModel方法,其实就是简单的返回泛型的一个对象。

(3)在Action提供一个泛型的私有对象,这里就是定义一个User的user对象,并提供相应的getter与setter。

好了,上面的三件事做完之后,Action就会去自动调用User的setter将表单中的name属性的值赋给User中的属性。而Action的后续处理的Jsp页面后者是Servlet就可以使用user对象了。

3.到底是用属性驱动和是模型驱动呢?

这个问题困扰了很多Struts2的初学者,我这里提供一些建议:

(1)请你统一整个系统中的Action使用的驱动模型,即要么都是用属性驱动,要么都是用模型驱动。

(2)如果你的DB中的持久层的对象与表单中的属性都是一一对应的话,那么就使用模型驱动吧,毕竟看起来代码要整洁得多。

(3)如果表单的属性不是一一对应的话,那么就应该使用属性驱动,否则,你的系统就必须提供两个Bean,一个对应表单提交的数据,另一个用与持久层。

看上面的例子,其实密码确认rpass是不需要放到DB中去的,而仅仅是用于校验密码的,不是吗?那么如果使用模型驱动的话,就存在这个问题了,而使用属性驱动的话又有些繁琐,现在我们就来调整一个看我的解决方法。

4.完整的例子

(1)表单提交的JSP页面index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@ taglib uri="/struts-tags" prefix="s"%><%    String path = request.getContextPath();    String basePath = request.getScheme() + "://"            + request.getServerName() + ":" + request.getServerPort()            + path + "/";%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html>    <head>        <base href="<%=basePath%>">        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">        <title>CSDN首页</title>    </head>    <body>        <s:a href="userManager/userRegister.jsp">用户注册</s:a>               <form action="register.do" name="SampleForm" method="post">            Username:<input type="text" name="uname"><br>            Password:<input type="password" name="upass"><br>            Confirm: <input type="password" name="rpass"><br>            <input type="submit" value="Submit">        </form>    </body></html>

(2)User的定义

package org.abu.csdn.action.user;import com.opensymphony.xwork2.ActionSupport;/** * Struts2属性驱动演示用的Java Bean * */public class User {    private String uname;    private String upass;     public String getUname() {        return uname;    }    public void setUname(String uname) {        this.uname = uname;    }    public String getUpass() {        return upass;    }    public void setUpass(String upass) {        this.upass = upass;    }    }

(3)RegisterAction的定义

package org.abu.csdn.action.user;import com.opensymphony.xwork2.ActionSupport;/** * Struts2属性驱动演示用的Action * */public class RegisterAction extends ActionSupport {    // 用来给spring注入,及属性拷贝    private User user;    private String uname;    private String upass;    private String rpass;    public String getUname() {        return uname;    }    public void setUname(String uname) {        this.uname = uname;    }    public String getUpass() {        return upass;    }    public void setUpass(String upass) {        this.upass = upass;    }    public String getRpass() {        return rpass;    }    public void setRpass(String rpass) {        this.rpass = rpass;    }       @Override    public String execute() throws Exception {        // 调用方法将属性copy到user中去,便于后续的service方法        copyAttribute();        // TODO:编写自己的user业务代码        return ActionSupport.SUCCESS;    }    /**     * 注意这是一个action全局的校验     */    @Override    public void validate() {        // 进行密码的校验        if (!(upass.trim()).equals((rpass.trim()))) {            // 注意这里addFieldError的fieldName参数必须用引号引起来,            // 不能这样使用addFieldError(rpass,"XXXXXX"),而必须是addFieldError("rpass","XXXXX")            this.addFieldError("rpass", this                    .getText("csdn.action.user.register.validate.verify"));        }    }    /**     * 将表单属性中需要持久化的属性拷贝到user中去     * @author 阿布     *    */    private void copyAttributes () {            user.setUname(uname);            user.setUpass(upass);    }}

(4)Struts.xml配置

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"    "http://struts.apache.org/dtds/struts-2.1.dtd"><struts>    <package name="root" extends="struts-default" namespace="/userManager">        <action name="userRegister" class="org.abu.csdn.action.user.RegisterAction">            <result name="success">/index.jsp</result>            <result name="input">/userManager/userRegister.jsp</result>        </action>                   </package></struts>


小结:

为什么要使用属性驱动和模型驱动

struts2与struts很大的不同点在于,struts的execute方法提供了HttpServletRequest和HttpServletResponse方法在获取客户端提交的数据信息的时候需要使用HttpServletRequest的getParameter()方法,并且还需要进行必要的数据类型转换。若客户端提交的数据量大的时候,我们则需要写很多的getParameter方法。这样代码量就相应的增加不少。但是struts2为我们提供了属性驱动和模型驱动,它不需要我们写很多的获取值的方法。而只需要我们在Action中定义相应的getter方法,在界面上以Action中的变量名作为表单元素的name属性值即可。

struts2 一切的工作都是由struts2的参数拦截器来完成的。

属性驱动。举个例子,页面上有个标签name="user" value="admin"。最后,提交到后台会以user=admin的形式。被拦截器获悉后,它就会查找action中是否有user这个参数,如果找到就调用setUser将admin赋给user。当请求返回的到jsp页面时,将jsp编译成servlet,如果页面中有name="user"的标签,或是直接用${user}的时候,拦截器会调用action中user参数的getUser方法,将user的值通过Response发送出去。
模型驱动(我理解的模型驱动就是用拦截器传递一个javaBean)原理一样。只不过需要两次调用getset方法。先调用javaBean的再调用具体参数的。struts2的模型驱动要实现ModelDriver<T>这个接口,并且还必须重写getModel()这个方法。

属性驱动和模型驱动有什么异同?

1.属性驱动

对于属性驱动,我们需要在 Action 中定义与表单元素对应的所有的属性,因而在 Action 中会出现很多的 getter 和 setter 方法。

2.模型驱动

对于模型驱动,使用的 Action 对象需要实现ModelDriven接口并给定所需要的类型.而在 Action 中我们只需要定义一个封装所有数据信息的 javabean 。

3.属性和模型驱动的相同点

当我们使用属性驱动和模型驱动的时候,必须将表单的元素中的 name 属性值与我们定义接收数据信息的变量名对应起来。


0 0