关于struts2的modelDriven
2014-10-30 13:52
183 查看
今天做毕业设计,前台往后台赋值,习惯性的用了modelDriven。但是刚写完就奇怪它的机理是怎样的,它怎么知道我前台传的参是哪个Model的属性(之前用servlet都是手动),于是手贱的ctrl点进去,简单了解了一下
之前记得要使用modelDriven必须使用modelDriven的拦截器,但是我没加这个拦截器也实现了功能,看默认拦截器defaultStack原来所谓的默认拦截器就是一系列拦截器的集合
看modelDriven的源码可以看到
发现它什么也没实现,就是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拦截器主要源码:
可以知道为什么要实现自动赋值,只需要实现modelDriven接口就行了
其中最重要逻辑代码是setParometers()方法
先判断提交过来的参数是否合法,因为提交过来的参数会影响到值栈所以struts2要对提交过来的参数进行合法性检查,以防止恶意用户的攻击,凡是请求参数中表达式中含有等号(=),逗号(,),#号(#)的都是非法表达式
至于怎么判断是否合法,我已经没兴趣了,知道是acceptableName(name)方法决定的。
了解了这么多感觉用的更随心所欲了。急需做无聊的毕业设计
之前记得要使用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中关于Session的使用
- 关于struts2
- 关于在struts2的文件简单上传
- 关于struts2,mysql,hibernate的开发环境下的中文显示为“问号”的问题总结
- 关于struts2中使用POI的方式导出EXCEL文件时的国际化问题
- struts2的关于method=“{1}"意思详解
- 关于Struts2的校验问题的若干意见(2)
- 关于struts2拦截器
- 关于struts2,mysql,hibernate的开发环境下的中文显示为“问号”的问题总结
- 关于Struts2的一些实例代码
- 关于Struts2环境搭建时导包的问题
- 关于struts2中datetimepicker显示的问题。
- 关于Struts2的校验问题的若干意见(1)
- 关于Struts2中的标签介绍(一)
- 关于学习STRUTS2的问题
- 关于Struts2 Checkboxlist 多个参数时不能默认选中
- 关于struts2和fckEditor或者ewebeditor结合中标签datetimepicker不能用的问题
- 关于struts2拦截器错误
- 关于Struts2的迭代标签与set标签的使用。
- struts2的标签:关于日期的标签