Struts2之使用ModelDriven完成的参数自动封装个人理解
2017-02-11 09:24
435 查看
前言
struts2提供了通过action实现modeldriven接口而自动封装我们需要的实体对象的功能,这个功能十分实用。因此就在想其实现原理是怎么样的,通过查看源码,得到一些答案,以下是我的理解。使用ModelDriven的示例
首先需要实体对象
public class CrmCourseType { /** * CREATE TABLE `crm_course_type` ( `courseTypeId` varchar(255) NOT NULL PRIMARY KEY, `courseCost` double DEFAULT NULL, `total` int(11) DEFAULT NULL, `courseName` varchar(500) DEFAULT NULL, `remark` varchar(5000) DEFAULT NULL ); */ private String courseTypeId; private Double courseCost; private Integer total; private String courseName; private String remark; private Set<CrmClass> crmClasses = new HashSet<CrmClass>(); private String totalStart; private String totalEnd; private String lessonCostStart; private String lessonCostEnd; public String getCourseTypeId() { return courseTypeId; } public void setCourseTypeId(String courseTypeId) { this.courseTypeId = courseTypeId; } public Double getCourseCost() { return courseCost; } public void setCourseCost(Double courseCost) { this.courseCost = courseCost; } public Integer getTotal() { return total; } public void setTotal(Integer total) { this.total = total; } public String getCourseName() { return courseName; } public void setCourseName(String courseName) { this.courseName = courseName; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public Set<CrmClass> getCrmClasses() { return crmClasses; } public void setCrmClasses(Set<CrmClass> crmClasses) { this.crmClasses = crmClasses; } public String getTotalStart() { return totalStart; } public void setTotalStart(String totalStart) { this.totalStart = totalStart; } public String getTotalEnd() { return totalEnd; } public void setTotalEnd(String totalEnd) { this.totalEnd = totalEnd; } public String getLessonCostStart() { return lessonCostStart; } public void setLessonCostStart(String lessonCostStart) { this.lessonCostStart = lessonCostStart; } public String getLessonCostEnd() { return lessonCostEnd; } public void setLessonCostEnd(String lessonCostEnd) { this.lessonCostEnd = lessonCostEnd; } }
Aciton类
public class CourseTypeAction extends ActionSupport implements ModelDriven<CrmCourseType> { // private CrmCourseType crmCourseType = new CrmCourseType(); //ervice private CourseTypeService courseTypeService; public void setCourseTypeService(CourseTypeService courseTypeService) { this.courseTypeService = courseTypeService; } public CrmCourseType getModel() { return crmCourseType; } /** * * @return */ public String findAll(){ List<CrmCourseType> allCourseType = this.courseTypeService.findAll(); ActionContext.getContext().put("allCourseType", allCourseType); return "findAll"; } }
另外在JSP表单中的name属性要与实体对象的属性名相同,以上的配置就可以说已经完成了,当访问CourseTypeAction时已经完成了其中的crmCourseType 实例已经封装了参数并且就是当前action中的具体实例,可以拿来直接操作。
实现分析之ModelDriven接口
该接口的作用是返回实例对象,并完成多态,使得在拦截器中可以方便的使用public interface ModelDriven<T> { /** * Gets the model to be pushed onto the ValueStack instead of the Action itself. * * @return the model */ T getModel(); }
这是该接口中的唯一方法。
实现核心之ModelDrivenInterceptor
其中的参数封装是在ParameterInterceptor拦截器中完成的,暂且不说,返回可以使用的bean对象则是在ModelDrivenInterceptor拦截器中完成的//核心代码 public String intercept(ActionInvocation invocation) throws Exception { //首先获取需要访问的action Object action = invocation.getAction(); //如果action实现了ModelDriven接口 if (action instanceof ModelDriven) { //通过多态将欲访问的action转化成ModelDriven的实现 ModelDriven modelDriven = (ModelDriven) action; //获取ValueStack ValueStack stack = invocation.getStack(); //获取实体对象,这就是必须要在action中new出对象的原因 Object model = modelDriven.getModel(); //如果对象存在,则入栈 if (model != null) stack.push(model); } //刷新实例(下面有具体分析) if (refreshModelBeforeResult) { invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model)); } } return invocation.invoke(); }
ModelDriven中有一个静态内部类RefreshModelBeforeResult,其作用就是判别在栈中是否有已存在的model实例,如果有就去除并放入当前实例,没有就放入当前的,简而言之就是刷新
protected static class RefreshModelBeforeResult implements PreResultListener { //原始实例 private Object originalModel = null; //实现了ModelDriven 的action对象 protected ModelDriven action; public RefreshModelBeforeResult(ModelDriven action, Object model) { this.originalModel = model; this.action = action; } public void beforeResult(ActionInvocation invocation, String resultCode) { //获取ValueStack ValueStack stack = invocation.getStack(); //得到ValueStack底层的CompoundRoot实现 CompoundRoot root = stack.getRoot(); //一开始设置需要刷新 boolean needsRefresh = true; //得到action中的新实例 Object newModel = action.getModel(); // 检查新实例是否已经在栈中 for (Object item : root) { if (item.equals(newModel)) { needsRefresh = false; } } // 将新实例插入栈中 if (needsRefresh) { // 删除原始实例 if (originalModel != null) { root.remove(originalModel); } if (newModel != null) { stack.push(newModel); } } } }
相关文章推荐
- 使用echarts类库,在后台封装option,提供两种使用struts2传递参数到页面的方法
- struts2(二) 表单参数自动封装和参数类型自动转换
- 回顾自动释放池的使用及个人理解autorelease
- Struts2(接受表单参数)请求数据自动封装和数据类型转换
- Struts2中使用框架完成自动验证
- Struts2参数的接收 使用DomainObject和ModelDriven
- struts2(二) 表单参数自动封装和参数类型自动转换
- Struts2 的参数封装理解
- struts2(三)之表单参数自动封装与参数类型自动转换
- struts2中自动封装参数及类型转换
- 关于在struts2中interceptor 中使用ActionInvocation 对象获得HttpServletRequest中封装的参数,以Map的形式
- Struts2_0900_ModelDrivenParamInput 使用ModelDriven接收参数
- Recyclerview的一些个人理解与使用(一)adapter的简单封装
- MASM32编程使用自动完成功能
- Atlas学习手记(4):使用AutoComplete Extender实现自动完成功能
- 使用EditPlus技巧,提高工作效率(附英文版、自动完成文件、语法文件下载)
- 使用EditPlus技巧,提高工作效率(附英文版、自动完成文件、语法文件下载)
- Struts2自带自动完成功能的问题
- 使用AutoCompleteExtender(自动完成下拉菜单)实例
- 使用AutoComplete Extender实现自动完成功能