---恢复内容开始---

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;
} }

所谓ModelDriven ,意思是直接把实体类当成页面数据的收集对象。比如,有实体类User 如上:

假如要写一个Action ,用来添加User 。
第一种做法是直接在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;
} } add_input.jsp: username:
password:
age:
address:

上述做法不好之处是:如果实体类的属性非常多,那么Action 中也要定义相同的属性。

第二种做法是将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;
} } add_input.jsp: username:
password:
age:
address:

这种做法不好的地方是:JSP 页面上表单域中的命名变得太长

第三种做法是利用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;
}
} JSP 的代码如下: username:
password:
age: 可见,第三种做法是比较好的,Action 和JSP 写起来都比较简单。 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( new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();
}

从ModelDrivenInterceptor 中,即可以看到model 对象被压入ValueStack 中!

其中的 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” ;
}

上述代码中,new UserManager().findUserById(user.getId()); 这一行,将从数据库中查询相应的记录,同时转换为User 对象返回。而return “ update_input ” ;将转向更新显示页面。

更新页面如下:

id: “>
username: “>
password: “>
age: “>
address: “>

上述代码运行起来之后,你在更新界面上将看不到数据(id 属性有值,其它属性无显示)。关键的原因是在执行到updateInput 之前,user 对象(在getMode() 方法中创建的对象)被压到ValueStack 中,这时候,UserAction 和ValueStack 都指向同一个user 对象;但紧接着,UserAction 中的user 被一个新的user 对象覆盖,这时候,UserAction 和ValueStack 不再指向同一个user 对象!ValueStack 中是旧的user 对象,而UserAction 中是新的user 对象!我们在JSP 中,直接通过username/address 等直接访问,当然是要访问ValueStack 中的旧user 对象,所以它们的属性都是空的(id 属性除外) !

理解上述问题很重要,当你理解了问题,那么问题的解决方法就可以有很多了:
比如,你可以把新对象的属性拷贝到旧对象上;比如,你可以先把旧对象从ValueStack 中移除,然后再把新对象压入ValueStack 等……

在最新的struts2 版本中,ModelDrivenInterceptor 提供了一个配置参数: refreshModelBeforeResult ,只要将它定义为true ,上述问题就被解决了!struts2 的解决方案就是:先把旧的model 对象从ValueStack 中移除,然后再把新的model 对象压入ValueStack

原文链接:http://www.jobui.com/mianshiti/it/jiagoushi/5975/

---恢复内容结束---

【转】为什么要使用ModelDriven的更多相关文章

  1. 6. ModelDriven拦截器、Preparable 拦截器

    1. 问题 Struts2 的 Action 我们将它定义为一个控制器,但是由于在 Action 中也可以来编写一些业务逻辑,也有人会在 Action 输入业务逻辑层. 但是在企业开发中,我们一般会将 ...

  2. Struts2中的ModelDriven机制及其运用

    所谓ModelDriven,意思是直接把实体类当成页面数据的收集对象.比如,有实体类User如下: package cn.com.leadfar.struts2.actions; public cla ...

  3. Struts2 DomainModel、ModelDriven接收参数

    一.DomainModel(域模型) 1. 应用场景:一般我们在struts2的action中接收参数通常是如下方式 package cn.orlion.user; import com.opensy ...

  4. 04传智_jbpm与OA项目_部门模块改进_直接在BaseAction中实现ModelDriven<T>

    这个项目是用Struts2做的,我这里单独写了一个BaseAction,用来存放所有的功能模块的Action的公共部分, 刚开始的做法是这个BaseAction只会继承ActionSupport 并不 ...

  5. Struts2中ModelDriven的陷阱及其预防

    页面表单 <form action="updateInput.action" method="post"> <input type=" ...

  6. Struts2中请求参数的接收方式和ModelDriven机制及其运用

    odelDriven 为什么需要ModelDriven 所谓ModelDriven,意思是直接把实体类当成页面数据的收集对象.比如,有实体类User如下: package cn.com.leadfar ...

  7. struts2重点——ModelDriven

    一.属性驱动 在目标 Action 类中,通过 setXxx() 方法来接收请求参数. 二.模型驱动 1.ParametersInterceptor 拦截器工作原理 ParametersInterce ...

  8. [原创]java WEB学习笔记65:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) ModelDriven拦截器 paramter 拦截器

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  9. Struts BaseAction工具类,封装Session,Request,Application,ModelDriven

    package com.ssh.shop.action; import java.io.InputStream; import java.lang.reflect.ParameterizedType; ...

  10. struts2 ModelDriven 和 Preparable 拦截器

    Struts2 运行流程图-1

随机推荐

  1. [转] kaldi中FST的可视化-以yesno为例

    http://blog.csdn.net/u013677156/article/details/77893661 1.kaldi解码过程 kaldi识别解码一段语音的过程是:首先提取特征,然后过声学模 ...

  2. 1.ActionBar

    ActionBar低版本和高版本用法不同 低版本:1. 引用v7-appcompat2. Activity继承ActionBarActivity3. android:theme="@styl ...

  3. 小奶狗给小喵咪上CSS课程

    小奶狗给小喵咪上CSS课程 小奶狗,你好啊? 小喵咪你好~ 听说学习HTML,要学习CSS是吗? 是的,小甜心~ 那么CSS是什么呢? CSS是Cascading Style Sheet英文的缩写,中 ...

  4. DevOps - 参考信息

    DevOps DevOps(Development+Operations)强调共同对业务目标负责,以实现用户价值作为唯一的评判标准:保证产品功能及时实现.成功部署和稳定使用: 是一种重视软件开发人员( ...

  5. 【zookeeper】4、利用zookeeper,借助观察模式,判断服务器的上下线

    首先什么是观察者模式,可以看看我之前的设计模式的文章 https://www.cnblogs.com/cutter-point/p/5249780.html 确定一下,要有观察者,要有被观察者,然后要 ...

  6. 分享一个基于web的满意度调查问卷源码系统

    问卷调查系统应用于各行各业,对于企业的数据回收统计分析战略决策起到至关作用.而现有的问卷调查系统大都是在线使用并将数据保存在第三方服务器上.这种模式每年都要缴纳费用并且数据安全性得不到保证.所以说每个 ...

  7. mysql 开发进阶篇系列 4 SQL 优化(各种优化方法点)

    1 通过handler_read 查看索引使用情况 如果索引经常被用到 那么handler_read_key的值将很高,这个值代表了一个行被索引值读的次数, 很低的值表明增加索引得到的性能改善不高,索 ...

  8. Spring系列之AOP的原理及手动实现

    目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 引入 到目前为止,我们已经完成了简易的IOC和DI的功能,虽然相比如Spring来说肯定是非常简陋的,但是毕竟我 ...

  9. 一个用于分页的page类

    今天周一,趁工作轻松,自己就写了一个基于MySQl数据库的分页查询,做分页,最主要的是以下几点: 一:写sql语句:比如查询某张数据表的数据,sql语句为:select * from table li ...

  10. 精读《dob - 框架使用》

    本系列分三部曲:<框架实现> <框架使用> 与 <跳出框架看哲学>,这三篇是我对数据流阶段性的总结,正好补充之前过时的文章. 本篇是 <框架使用>. 1 ...