Struts(十七):通过CURD来学习paramsPrepareParams拦截器栈
- 背景:
通过上一章节《Struts(十六):通过CURD来学习Struts流程及ModelDriven的用法》学习了ModelDriven拦截器的用法,上章节中讲到了edit功能。
要修改一个member信息时:
1、首先通过url传入一个id参数:member-list.jsp中
<td><s:a href="member-view.action?id=%{id}" >view</s:a></td> <td><s:a href="member-edit.action?id=%{id}" >edit</s:a></td> <td><s:a href="member-delete.action?id=%{id}" >delete</s:a></td>
2、MemberAction.java的edit函数:
public String edit() { // 1、根据id从数据库中,获取id对应的member对象 Member member_ = memberDao.get(this.member.getId()); // 2、把从数据库中获取的属性放入值栈的属性中 this.member.setAge(member_.getAge()); this.member.setName(member_.getName()); this.member.setGender(member_.getGender()); return "edit"; }
3、表单form-edit.jsp:
<s:debug></s:debug> <s:form action="member-save.action"> <s:textfield name="id" label="ID"></s:textfield> <s:textfield name="name" label="Name"></s:textfield> <s:textfield name="age" label="Age"></s:textfield> <s:radio list="#{'male':'male','female':'female' }" name="gender" label="Gender"></s:radio> <s:submit name="submit" label="提交"></s:submit> </s:form>
流程分析图:
根据上边的代码,调试form-edit.jsp页面当打开s:debug我们确实看到了栈顶对象被填充值了:
4、修改MemberAction.java的edit方法,并调试产看member-edit.jsp debug内容:
public String edit() { // // 1、根据id从数据库中,获取id对应的member对象 // Member member_ = memberDao.get(this.member.getId()); // // // 2、把从数据库中获取的属性放入值栈的属性中 // this.member.setAge(member_.getAge()); // this.member.setName(member_.getName()); // this.member.setGender(member_.getGender()); // this.member= memberDao.get(this.member.getId()); return "edit"; }
这是为什么呢?
---getModel()返回的对象是存放在栈顶的对象,而修改后的对象是Dao中返回的对象,这两个对象不是同一个对象的原因。
我们是否能通过其他方式来实现这个功能呢?
- 自动填写了memeber-edit.jsp表单页面改写方案(paramsPrepareParamsStack方案)
方案一:把重新赋值后的this.member对象压入栈顶
public String edit() { // // 1、根据id从数据库中,获取id对应的member对象 // Member member_ = memberDao.get(this.member.getId()); // // // 2、把从数据库中获取的属性放入值栈的属性中 // this.member.setAge(member_.getAge()); // this.member.setName(member_.getName()); // this.member.setGender(member_.getGender()); this.member = memberDao.get(this.member.getId()); ActionContext.getContext().getValueStack().push(this.member); return "edit"; }
不错这样是可以自动填写了memeber-edit.jsp表单页面,但是我们查看s:debug下发现值栈中有两个member对象:
方案二:使用paramsPrepareParams拦截器栈
1、修改struts.xml来实现修改当前项目struts2的拦截器栈
在package标签下添加配置:<default-interceptor-ref name="paramsPrepareParamsStack"></default-interceptor-ref>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.ognl.allowStaticMethodAccess" value="true" /> <constant name="struts.devMode" value="false" /> <package name="default" namespace="/" extends="struts-default"> <default-interceptor-ref name="paramsPrepareParamsStack"></default-interceptor-ref> <action name="member-*" class="com.dx.struts.actions.MemberAction" method="{1}"> <result name="{1}">/member-{1}.jsp</result> <result name="delete" type="redirectAction">member-list</result> <result name="modify" type="redirectAction">member-list</result> <result name="create" type="redirectAction">member-list</result> </action> </package> <!-- Add packages here --> </struts>
2、对MemberAction.java进行修改:
1)添加id属性,并实现其set方法,目的是:实现在调用ModelDriven的getModel函数前,通过Params调用该set方法实现对id属性赋值,因此可以在getModel内部使用该属性判定是否页面传递了该参数。
2)修改MemberAction.java自身方法。
修改后代码如下:
/** * @author Administrator * */ package com.dx.struts.actions; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.struts2.interceptor.RequestAware; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ModelDriven; import com.dx.struts.dao.MemberDao; import com.dx.struts.entity.Member; /** * ModelDriven 和Preparable拦截器 */ public class MemberAction implements RequestAware, ModelDriven<Member> { private MemberDao memberDao = new MemberDao(); private Member member; private Long id; // Params拦截器 负责赋值id时,调用了该函数。 public void setId(Long id) { this.id = id; } public String list() { List<Member> members = memberDao.getMembers(); request.put("members", members); return "list"; } public String view() { // // 1、获取传入的id:member.getId(); // // 2、根据id获取member对象; // Member member_ = memberDao.get(this.member.getId()); // // // 3、赋值栈顶对象的属性:此时栈顶对象为member对象。 // member_.setAge(this.member.getAge()); // member_.setName(this.member.getName()); // member_.setGender(this.member.getGender()); // return "view"; } public String delete() { // memberDao.remove(this.member.getId()); memberDao.remove(this.id); // 返回结果的类型应该为:redirectAction // 也可以是chain:实际上chain是没有必要的,因为不需要在下一个action中保留啊当前action的状态 // 若使用chain,则到达目标页面后,地址栏显示的依然是删除的那个链接,则刷新时会重复提交。 return "delete"; } public String edit() { // // 1、根据id从数据库中,获取id对应的member对象 // Member member_ = memberDao.get(this.member.getId()); // // // 2、把从数据库中获取的属性放入值栈的属性中 // this.member.setAge(member_.getAge()); // this.member.setName(member_.getName()); // this.member.setGender(member_.getGender()); // this.member = memberDao.get(this.member.getId()); // ActionContext.getContext().getValueStack().push(this.member); return "edit"; } public String save() { //.... return "modify"; } public String create() { member.setId(new Date().getTime()); memberDao.add(member); return "create"; } private Map<String, Object> request; @Override public void setRequest(Map<String, Object> request) { this.request = request; } @Override public Member getModel() { // 如果需要在这个函数调用调用了ModelDriven拦截器栈之前就初始化参数id的拦截器栈的Params拦截器。 // 经过查看DefaultStack拦截器栈中ModelDriven拦截器之前并没有Params拦截器,说明该默认拦截器已经不够用了, // 但是我们发现在struts2-core.jar下struts-default.xml下除了DefaultStack拦截器栈外还有paramsPrepareParamsStack拦截器栈, // 而该拦截器栈中恰好在ModelDriven拦截器栈之前和之后都调用了一次Params拦截器。 // 修改struts.xml package标签下添加配置:<default-interceptor-ref name="paramsPrepareParamsStack"></default-interceptor-ref> // 如果没有id请求参数,说明为create if (this.id == null) { this.member = new Member(); } // 如果有id请求参数,说明为edit else { this.member = memberDao.get(this.id); } return this.member; } }
- 值栈paramsPrepareParamsStack方案总结
不足之处(资源浪费):
1、在执行删除的时候,id不为null,但是getModel方法执行了一次从数据库中空加载;
2、当执行查询信息时,也空执行了一次new Member()对象。
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。