Struts2 的ModelDriven 二——ModelDrive
2018-05-12 10:12
435 查看
继上篇博客介绍了值传递的几种形式,这篇博客,来说说struts2是如何实现的?
有这么两个概念和modelDriven实现有关:ValueStack,ModelDrivenInterceptor。
下面是该拦截器intercept方法源码:
此方法就是就是把getModel方法返回的结果压入值栈而已,我们一般实现这个接口是利用压入值栈的model对象接收从页面提交过来的数据,因为Action也是在值栈中,而struts2在赋值参数的时候是在值栈从栈顶往栈底寻找有相应setter方法的对象,而这时model压入了值栈,它是处于栈顶的,所以从页面提交过来的参数也就被model对象接收了。
ValueStack实际上就是对OGNL的封装,OGNL主要的功能就是赋值与取值,Struts2正是通过ValueStack来进行赋值与取值的!
ValueStack是一个接口,而OgnlValueStack是strtus2中的缺省实现。ValueStack中的数据,分两个部分存放:root和context(这与OGNL中的概念一致),同时ValueStack暴露相关的接口:
void setValue(String expr, Object value);
Object findValue(String expr);
用来通过OGNL表达式对ValueStack中的数据进行操作!
ValueStack中的root对象是CompoundRoot,CompoundRoot继承了ArraryList,提供了额外的方法:push()和pop()方法,用来对root对象中所包含的数据进行存取!
正是通过这两个方法,CompoundRoot变成了一个栈结构!压栈操作,将导致对象被放到CompoundRoot的第0个元素上(第0个元素 是栈顶),其它对象被依次往后移动;出栈操作,将导致CompoundRoot的第0个元素被移除(即栈顶元素被弹出),其它对象被依次往前移动!
OGNL不支持多个root对象,而struts2能够支持多个root对象,它对OGNL做了扩展。
如果某个OGNL表达式被传递给ValueStack(即调用ValueStack的setValue或findValue方法),而表达式中包含 有对root对象的访问操作,ValueStack将依次从栈顶往栈底搜索CompoundRoot对象中所包含的对象,看哪个对象具有相应的属性,找到 之后,立刻返回。
接下来,我们看 存 的实现,其实就是博客开篇提到的,三种方法,一个原则:前台 控件的name必须是和实体属性名称是一致的。这里不再赘述。
主要是看 “取” 的实现。
服务器端,我们需要手动将model 压入 ValueStack:ActionContext.getContext().getValueStack().push(××);
在JSP中: 对应的JSP使用 struts2标签 + ognl 来取。
或者:
1、客户端请求:当一个请求过来,首先被modelDriveInterceptor拦截,执行getModel方法,压入valueStack,ValueStack 将请求的值和压入的model进行对比赋值;
2、服务端回发:我们需要把model push进ValueStack。前台使用 struts2标签 + ognl来接受,解析。
有这么两个概念和modelDriven实现有关:ValueStack,ModelDrivenInterceptor。
一、ModelDrivenInterceptor
首先先介绍以下ModelDrivenInterceptor,该拦截器处于defaultStack第九的位置。ModelDrivenInterceptor拦截器主要做的事就是调用Action的getModel()方法然后把返回的model压入值栈。下面是该拦截器intercept方法源码:
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(); }
此方法就是就是把getModel方法返回的结果压入值栈而已,我们一般实现这个接口是利用压入值栈的model对象接收从页面提交过来的数据,因为Action也是在值栈中,而struts2在赋值参数的时候是在值栈从栈顶往栈底寻找有相应setter方法的对象,而这时model压入了值栈,它是处于栈顶的,所以从页面提交过来的参数也就被model对象接收了。
二、ValueStack
这个ValueStack和 struts的ognl是分不开的。(valueStack是接口,ognl实现了该接口)ValueStack实际上就是对OGNL的封装,OGNL主要的功能就是赋值与取值,Struts2正是通过ValueStack来进行赋值与取值的!
ValueStack是一个接口,而OgnlValueStack是strtus2中的缺省实现。ValueStack中的数据,分两个部分存放:root和context(这与OGNL中的概念一致),同时ValueStack暴露相关的接口:
void setValue(String expr, Object value);
Object findValue(String expr);
用来通过OGNL表达式对ValueStack中的数据进行操作!
ValueStack中的root对象是CompoundRoot,CompoundRoot继承了ArraryList,提供了额外的方法:push()和pop()方法,用来对root对象中所包含的数据进行存取!
public class CompoundRoot extends ArrayList { public CompoundRoot() { } public CompoundRoot(List list) { super(list); } public CompoundRoot cutStack(int index) { return new CompoundRoot(subList(index, size())); } public Object peek() { return get(0); } public Object pop() { return remove(0); } public void push(Object o) { add(0, o); } }
正是通过这两个方法,CompoundRoot变成了一个栈结构!压栈操作,将导致对象被放到CompoundRoot的第0个元素上(第0个元素 是栈顶),其它对象被依次往后移动;出栈操作,将导致CompoundRoot的第0个元素被移除(即栈顶元素被弹出),其它对象被依次往前移动!
OGNL不支持多个root对象,而struts2能够支持多个root对象,它对OGNL做了扩展。
如果某个OGNL表达式被传递给ValueStack(即调用ValueStack的setValue或findValue方法),而表达式中包含 有对root对象的访问操作,ValueStack将依次从栈顶往栈底搜索CompoundRoot对象中所包含的对象,看哪个对象具有相应的属性,找到 之后,立刻返回。
三、存与 取 的实现
这里的存是:客户端请求中的参数如何被 “存” 进 ValueStack,例如:添加操作;而 “取” 是指服务器查询数据,如何回显到前台页面,例如 更新操作。接下来,我们看 存 的实现,其实就是博客开篇提到的,三种方法,一个原则:前台 控件的name必须是和实体属性名称是一致的。这里不再赘述。
主要是看 “取” 的实现。
服务器端,我们需要手动将model 压入 ValueStack:ActionContext.getContext().getValueStack().push(××);
public class UserAction { //查看用户的详细信息 public String detail() { User u = new User(); u.setUsername("wyx"); ActionContext.getContext().getValueStack().push(u); return "update"; } }
在JSP中: 对应的JSP使用 struts2标签 + ognl 来取。
username:<input type="text" name="username" value="<s:property value="username"/>"> <br/>
或者:
<s:textfield name="username"/>
总结
所以struts2的modelDriven机制:1、客户端请求:当一个请求过来,首先被modelDriveInterceptor拦截,执行getModel方法,压入valueStack,ValueStack 将请求的值和压入的model进行对比赋值;
2、服务端回发:我们需要把model push进ValueStack。前台使用 struts2标签 + ognl来接受,解析。
相关文章推荐
- Struts2 的ModelDriven 二——ModelDrive
- Struts2中ModelDriven的作用以及遍历栈顶的list,map
- struts2使用modeldriven执行转向更新页面是直接将getByID()获取到的值赋值给model数据不回显
- struts2之ModelDriven的使用问题
- Struts2 学习系列 (5) ModelDriven 和 Preparable 拦截器
- struts2之ModelDriven的使用
- Struts2 的 Preparable, ModelDriven 接口方法里无法获得参数,理解 拦截器与责任链
- Struts2 DomainModel、ModelDriven接收参数
- struts2的整体回顾(ACTION、拦截器、值栈、OGNL表达式、ModelDriven方案等)
- 【Struts2进阶】Struts2深度解析ModelDriven原理
- struts2之ModelDriven
- Struts2的整体回顾(Action, 拦截器, 值栈, OGNL表示式, ModelDriven)
- Struts2接口之ModelDriven分析
- struts2之ModelDriven的用法
- Struts2之ModelDriven的使用
- 关于Struts2的Model Driven
- Struts2的模型驱动(ModelDriven)
- Struts2之ModelDriven的使用
- struts2的ModelDriven
- struts2的整体回顾(ACTION、拦截器、值栈、OGNL表达式、ModelDriven方案等)