Struts2浅析 之 模型驱动与属性驱动
2016-06-12 23:39
351 查看
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 属性值与我们定义接收数据信息的变量名对应起来。
相关文章推荐
- JQuery+Strusts1.x无刷新登录
- ActionScript 3.0 编程体验
- 再谈Jquery Ajax方法传递到action(补充)
- 详解Webwork中Action 调用的方法
- ASP.NET MVC:Filter和Action的执行介绍
- jQuery中设置form表单中action值的实现方法
- NopCommerce架构分析之(五)Model绑定Action参数
- jQuery改变form表单的action,并进行提交的实现代码
- 使用jquery提交form表单并自定义action的实现代码
- Ajax in action 英文版配书源码 下载
- ajax使用不同namespace的action的方法
- JSP教程之使用JavaBean完成业务逻辑的方法
- js实现接收表单的值并将值拼在表单action后面的方法
- JSP学习之JavaBean用法分析
- ajax交互Struts2的action(客户端/服务器端)
- java struts常见错误以及原因分析
- Flex弹出窗口请求Action函数示例
- Struts之logic标签库详解
- 通过实例深入学习Java的Struts框架中的OGNL表达式使用
- 用JS动态改变表单form里的action值属性的两种方法