ModelDriven:模型驱动,对所有action的模型对象进行批处理. 我们在开发中, 在action中一般是用实体对象,然后给实体对象get,set方法。 RegAction{ 然后在jsp页面中给action中的user属性绑定值是通过如下方式 <s:textfield name="user.name" /> 这样都要加上user.因为在值栈中action进入值栈的时候,值栈中存储的值就是以user.name这种形式存在的,所以ognl搜索值栈的时候,也要按这个名字来搜索。 这样就 比较麻烦,于是就引入了模型驱动。 引入模型驱动后在jsp页面绑定属性值的时候就可以不用加上user. 如: <s:textfield name="name" /> 原理是什么: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 { 也就是不处在栈顶。即使把当前new出的user赋值给属性user也不行,因为在值栈中是通过引用来实现,即值栈中是对象的地址。 public String Edit() { User u = new User(); u.setId(uid); u.setName("jerry"); 如果要把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中的信息 } } |
|