Struts2中的ModelDriven机制及其运用
2015-09-21 14:54
197 查看
转自:http://blog.csdn.net/li_tengfei/article/details/6098145
为什么需要ModelDriven
Action的属性要加入值栈,值栈里面才有action的属性的值。所谓ModelDriven,意思是直接把实体类当成页面数据的收集对象。比如,有实体类User如下:
package cn.com.leadfar.struts2.actions; public class User { private int id; private String username; private String password; private int age; private String address; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getId() { return id; } public void setId(int id) { this.id = id; } } |
第一种做法是直接在Action中定义所有需要的属性,然后在JSP中直接用属性名称来提交数据:
UserAction:
public class UserAction { private int id; private String username; private String password; private int age; private String address; public String add(){ User user = new User(); user.setId(id); user.setUsername(username); user.setPassword(password); user.setAge(age); user.setAddress(address); new UserManager().addUser(user); return "success"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } |
<form action="test/user.action" method="post"> <input type="hidden" name="method:add"> username:<input type="text" name="username"> <br/> password:<input type="text" name="password"> <br/> age:<input type="text" name="age"> <br/> address:<input type="text" name="address"> <br/> <input type="submit" name="submit" value="添加用户"> </form> <br/> |
第二种做法是将User对象定义到UserAction中,然后在JSP中通过user属性来给user赋值:
UserAction:
public class UserAction { private User user; public String add(){ new UserManager().addUser(user); return "success"; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } |
<form action="test/user.action" method="post"> <input type="hidden" name="method:add"> username:<input type="text" name="user.username"> <br/> password:<input type="text" name="user.password"> <br/> age:<input type="text" name="user.age"> <br/> address:<input type="text" name="user.address"> <br/> <input type="submit" name="submit" value="添加用户"> </form> <br/> |
第三种做法是利用ModelDriven机制,让UserAction实现一个ModelDriven接口,同时实现接口中的方法:getModel()。如下所示:
public class UserAction implements ModelDriven{ private User user; @Override public Object getModel() { if(user == null){ user = new User(); } return user; } public String add(){ new UserManager().addUser(user); return "success"; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } |
<form action="test/user.action" method="post"> <input type="hidden" name="method:add"> username:<input type="text" name="username"> <br/> password:<input type="text" name="password"> <br/> age:<input type="text" name="age"> <br/> <input type="submit" name="submit" value="添加用户"> </form> <br/> |
ModelDriven背后的机制?
ModelDriven背后的机制就是ValueStack。界面通过:username/age/address这样的名称,就能够被直接赋值给user对象,这证明user对象正是ValueStack中的一个root对象!那么,为什么user对象会在ValueStack中呢?它是什么时候被压入ValueStack的呢?答案是:ModelDrivenInterceptor(关于Interceptor的概念,请参考后续章节的说明)。ModelDrivenInterceptor是缺省的拦截器链的一部分,当一个请求经过ModelDrivenInterceptor的时候,在这个拦截器中,会判断当前要调用的Action对象是否实现了ModelDriven接口,如果实现了这个接口,则调用getModel()方法,并把返回值(本例是返回user对象)压入ValueStack。
请看ModelDrivenInterceptor的代码:
public class ModelDrivenInterceptor extends AbstractInterceptor { protected boolean refreshModelBeforeResult = false; public void setRefreshModelBeforeResult(boolean val) { this.refreshModelBeforeResult = val; } @Override public String intercept(ActionInvocation invocation) throws Exception { Object action = invocation.getAction(); if (action instanceof ModelDriven) { ModelDriven modelDriven = (ModelDriven) action; ValueStack stack = invocation.getStack(); Object model = modelDriven.getModel(); if (model != null) { stack.push(model); } if (refreshModelBeforeResult) { invocation.addPreResultListener(newRefreshModelBeforeResult(modelDriven, model)); } } return invocation.invoke(); } |
其中的refreshModelBeforeResult是为了接下来描述的一个问题而提供的解决方法。
理解常见的陷阱及其解决方法
假设我们要更新一个实体对象,那么第一步首先是打开更新界面,请看下述模拟打开更新界面的代码:public class UserAction implements ModelDriven{ private User user; @Override public Object getModel() { if(user == null){ user = new User(); //user.setUsername("这是原来的User对象"); } return user; } public String updateInput(){ //根据ID,查询数据库,得到User对象 user = new UserManager().findUserById(user.getId()); return "update_input"; } |
更新页面如下:
<form action="test/user.action" method="post"> <input type="hidden" name="method:update"> id:<input type="text" name="id" value="<s:property value="id"/>"> <br/> username:<input type="text" name="username" value="<s:property value="username"/>"> <br/> password:<input type="text" name="password" value="<s:property value="password"/>"> <br/> age:<input type="text" name="age" value="<s:property value="age"/>"> <br/> address:<input type="text" name="address" value="<s:property value="address"/>"> <br/> <input type="submit" name="submit" value="更新用户"> </form> <br/> |
如果你使用了Struts2提供的 ModelDrivenInterceptor,则它会把Action对象的getModel()方法得到的对象存入值栈中。此时,值栈最底层为Action类,其次为这个model。此时值栈中有2个地方有user。
理解上述问题很重要,当你理解了问题,那么问题的解决方法就可以有很多了:
比如,你可以把新对象的属性拷贝到旧对象上;比如,你可以先把旧对象从ValueStack中移除,然后再把新对象压入ValueStack等……
在最新的struts2版本中,ModelDrivenInterceptor提供了一个配置参数:refreshModelBeforeResult,只要将它定义为true,上述问题就被解决了!struts2的解决方案就是:先把旧的model对象从ValueStack中移除,然后再把新的model对象压入ValueStack!
相关文章推荐
- javase 集合的subList方法
- 定位Java运行时 代码段方法
- java Struts2 框架的搭建与简单的登录验证
- ubuntu安装javaweb
- java中存在的内存泄漏
- JVM:查看java内存情况命令
- Java 利用DFA算法 屏蔽敏感词
- JAVA Socket获取服务端信息
- java 连接sql server2008数据库配置
- java中如何判断类的重复加载
- java判断字符串是否为空的方式
- The JAVA_HOME environment variable does not point to a working 32-bit JDK or JRE.
- JAVA Socket连接服务器时可能抛出的异常
- Java编程思想重点笔记
- java与数据库连接(JDBC)
- java 计算经度纬度之间的距离
- SpringMVC中使用Interceptor拦截器
- JavaEE问题之jdk问题
- 【转】Description Resource Path Location Type Java compiler level&n
- Java性能分析小工具 ---- jconsole