关于struts2的modelDriven
今天做毕业设计,前台往后台赋值,习惯性的用了modelDriven。但是刚写完就奇怪它的机理是怎样的,它怎么知道我前台传的参是哪个Model的属性(之前用servlet都是手动),于是手贱的ctrl点进去,简单了解了一下
之前记得要使用modelDriven必须使用modelDriven的拦截器,但是我没加这个拦截器也实现了功能,看默认拦截器defaultStack原来所谓的默认拦截器就是一系列拦截器的集合
看modelDriven的源码可以看到
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//获取 Action 对象: EmployeeAction 对象, 此时该 Action 已经实现了 ModelDriven 接口
//public class EmployeeAction implements RequestAware, ModelDriven<Employee>
Object action = invocation.getAction();
//判断 action 是否是 ModelDriven 的实例
if (action instanceof ModelDriven) {
//强制转换为 ModelDriven 类型
ModelDriven modelDriven = (ModelDriven) action;
//获取值栈
ValueStack stack = invocation.getStack();
//调用 ModelDriven 接口的 getModel() 方法
//即调用 EmployeeAction 的 getModel() 方法
/*
public Employee getModel() {
employee = new Employee();
return employee;
}
*/
Object model = modelDriven.getModel();
if (model != null) {
//把 getModel() 方法的返回值压入到值栈的栈顶. 实际压入的是 EmployeeAction 的 employee 成员变量
stack.push(model);
}
if (refreshModelBeforeResult) {
invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();
发现它什么也没实现,就是modelDriven接口,如果实现了就调用了它的getModel方法,然后把得到的压入栈顶。没有赋值操作
那么流程图应该是这样:

那么setName()赋值操作是谁做的?ParametersInterceptor
那么结论是:
1)ModelDrivenInterceptor只是将实现了ModelDriven的action的model放入值栈而已,所以你才可以直接使用
<input type="text" name="type" />传值。
2)如果action没有实现此接口,那么配置ModelDrivenInterceptor没有任何意义
3)ModelDrivenInterceptor并不负责注入值,赋值的是ParametersInterceptor
如果还要深究的话
ParametersInterceptor拦截器继承自MethodFilterInterceptor,其主要功能是把ActionContext中的请求参数设置到ValueStack中,如果栈顶是当前Action则把请求参数设置到了Action中,如果栈顶是一个model(Action实现了ModelDriven接口)则把参数设置到了model中。
ParametersInterceptor拦截器主要源码:
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();//获取当前执行的Action对象
if (!(action instanceof NoParameters)) {//判断Action是否实现了NoParameters接口,实现该接口表示该Action没有任何请求参数
ActionContext ac = invocation.getInvocationContext();//获取ActionContext对象
final Map<String, Object> parameters = retrieveParameters(ac);//获取请求参数Map
//省略...
if (parameters != null) {//如果请求参数不为null
Map<String, Object> contextMap = ac.getContextMap();//获取ActionContext内部的context Map,即OgnlContext对象
try {
//省略...
ValueStack stack = ac.getValueStack();//获取值栈
setParameters(action, stack, parameters);//为值栈设置参数
} finally {
//省略...
}
}
}
return invocation.invoke();//调用下一个拦截器
}
可以知道为什么要实现自动赋值,只需要实现modelDriven接口就行了
其中最重要逻辑代码是setParometers()方法
protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) {
ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware)
? (ParameterNameAware) action : null;//判断Action有无实现ParameterNameAware接口
Map<String, Object> params;
Map<String, Object> acceptableParameters;//合法参数集合
//判断参数设置是否有序,ordered默认为false,即无序
if (ordered) {
params = new TreeMap<String, Object>(getOrderedComparator());//如果有序则要获取比较器
acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());
params.putAll(parameters);
} else {
params = new TreeMap<String, Object>(parameters);
acceptableParameters = new TreeMap<String, Object>();
}
//迭代请求参数
for (Map.Entry<String, Object> entry : params.entrySet()) {
String name = entry.getKey();
//判断参数是否合法,如果Action实现了ParameterNameAware则acceptableName(name)返回true且parameterNameAware.acceptableParameterName(name)
//也返回true该参数才是合法的;如果Action没有实现ParameterNameAware则参数是否合法由acceptableName(name)方法决定
boolean acceptableName = acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name));
//如果参数合法
if (acceptableName) {
acceptableParameters.put(name, entry.getValue());//把合法参数添加到合法参数集合中
}
}
ValueStack newStack = valueStackFactory.createValueStack(stack);
//省略...
for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {//迭代合法参数
String name = entry.getKey();//参数名
Object value = entry.getValue();//参数值
try {
newStack.setValue(name, value);//将该参数设置到ValueStack中
} catch (RuntimeException e) {
//省略...
}
}
//省略...
//看该方法的名称是将合法参数添加到ActionContext中,但在该拦截器中,该方法为空实现,无任何代码
//该方法被声明为protected,即子类可以覆盖该方法以改变行为
addParametersToContext(ActionContext.getContext(), acceptableParameters);
}
先判断提交过来的参数是否合法,因为提交过来的参数会影响到值栈所以struts2要对提交过来的参数进行合法性检查,以防止恶意用户的攻击,凡是请求参数中表达式中含有等号(=),逗号(,),#号(#)的都是非法表达式
至于怎么判断是否合法,我已经没兴趣了,知道是acceptableName(name)方法决定的。
了解了这么多感觉用的更随心所欲了。急需做无聊的毕业设计
关于struts2的modelDriven的更多相关文章
- 接触Struts2的ModelDriven<>接口
最近在学SSH框架,实战项目,用到了Struts2的ModelDriven<>接口,在这做一点记录 ModelDriven,意为模型驱动,意思是直接把实体类当成页面数据的收集对象 参考他人 ...
- struts2重点——ModelDriven
一.属性驱动 在目标 Action 类中,通过 setXxx() 方法来接收请求参数. 二.模型驱动 1.ParametersInterceptor 拦截器工作原理 ParametersInterce ...
- Struts2中ModelDriven的使用
它是Struts2种独有的一种接收用户输入的机制,想在项目中使用模型驱动 (ModelDriven)需要让Action实现com.opensymphony.xwork2.ModelDriven 接口, ...
- Struts2 之 modelDriven & prepare 拦截器详解
struts2 ModelDriven & Prepareable 拦截器 前面对于 Struts2 的开发环境的搭建.配置文件以及 Struts2 的值栈都已经进行过叙述了!这次博文我们讲解 ...
- Struts2之ModelDriven和Preparable拦截器
首先struts.xml文件配置如下 默认拦截器设置为paramsPrepareParamsStack <package name="default" namespace=& ...
- struts2之ModelDriven的用法
在Struts 2中,提供了另外一种直接使用领域对象的方式,就是让action实现com.opensymphony. xwork2.ModelDriven接口.ModelDriven让你可以直接操作应 ...
- Struts2之ModelDriven的使用
http://www.cnblogs.com/luoyanli/archive/2012/11/20/2778361.html 我们可以根据Action属性的不同将它分为两类:Field-Driven ...
- struts2之ModelDriven
在Struts 2中,提供了另外一种直接使用领域对象的方式,就是让action实现com.opensymphony. xwork2.ModelDriven接口.ModelDriven让你可以直接操作应 ...
- Struts2中ModelDriven的陷阱及其预防
页面表单 <form action="updateInput.action" method="post"> <input type=" ...
随机推荐
- HTTPS 升级指南
上一篇文章我介绍了 HTTP/2 协议 ,它只有在 HTTPS 环境才会生效. 为了升级到 HTTP/2 协议,必须先启用 HTTPS.如果你不了解 HTTPS 协议(学名 TLS 协议),可以参考我 ...
- jxse2.6连接外网rdv一直连接不上,而相同的代码用jxse2.7却能连上
一直以为2.6中的bug会少一些,所以用2.6做开发:之前测试一直是在同一台 机器上,所以没啥问题:最近在外网设置了一个rdv,却一直连不上,困扰了n久,尝试各种方式都不起作用.最后想起以前开发的代码 ...
- Hibernate之基于外键映射的一对一(1-1)关联关系
1.对于基于外键的1-1关联,其外键可以存放在任意一边,在需要存放外键一端,增加many-to-one元素.为many-to-one元素增加unique="true"属性来表示为1 ...
- Hive自定义UDAF详解
遇到一个Hive需求:有A.B.C三列,按A列进行聚合,求出C列聚合后的最小值和最大值各自对应的B列值.这个需求用hql和内建函数也可完成,但是比较繁琐,会解析成几个MR进行执行,如果自定义UDAF便 ...
- 自定义控件和XControl控件
(1)LabVIEW的自定义控件,实际上就是对LabVIEW自带的控件的一种修改,但是这种修改只能改变它的外观,即大小.颜色.位置等等,但是功能是改变不了的.如你对一个按钮进行自定义控件,无论怎么改, ...
- poj 1679 http://poj.org/problem?id=1679
http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submis ...
- ASP.NET MVC 前端(View)向后端(Controller)中传值
在MVC中,要把前端View中的值传递给后端Controller, 主要有两种方法 1. 利用Request.Form 或者 Request.QueryString public ActionResu ...
- 转载 SQL Server中索引管理之六大铁律
转载原地址 http://jingyan.baidu.com/article/48a42057c03bd7a924250429.html 索引是以表列为基础的数据库对象.索引中保存着表中排序的索引列, ...
- Codeforces Round #245 (Div. 1) B. Working out (简单DP)
题目链接:http://codeforces.com/problemset/problem/429/B 给你一个矩阵,一个人从(1, 1) ->(n, m),只能向下或者向右: 一个人从(n, ...
- HDU/杭电2013多校第三场解题报告
今天悲剧了,各种被虐啊,还是太年轻了 Crime 这道题目给的时间好长,第一次就想到了暴力,结果华丽丽的TLE了. 后来找了一下,发现前24个是1, 2, 6, 12, 72, 72, 864, 17 ...