您的位置:首页 > 编程语言 > Java开发

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);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  struts2.0 modeldrive