今天做毕业设计,前台往后台赋值,习惯性的用了modelDriven。但是刚写完就奇怪它的机理是怎样的,它怎么知道我前台传的参是哪个Model的属性(之前用servlet都是手动),于是手贱的ctrl点进去,简单了解了一下


之前记得要使用modelDriven必须使用modelDriven的拦截器,但是我没加这个拦截器也实现了功能,看默认拦截器defaultStack原来所谓的默认拦截器就是一系列拦截器的集合

看modelDriven的源码可以看到

  1. @Override
  2.  
  3. public String intercept(ActionInvocation invocation) throws Exception {
  4.  
  5. //获取 Action 对象: EmployeeAction 对象, 此时该 Action 已经实现了 ModelDriven 接口
  6.  
  7. //public class EmployeeAction implements RequestAware, ModelDriven<Employee>
  8.  
  9. Object action = invocation.getAction();
  10.  
  11. //判断 action 是否是 ModelDriven 的实例
  12.  
  13. if (action instanceof ModelDriven) {
  14.  
  15. //强制转换为 ModelDriven 类型
  16.  
  17. ModelDriven modelDriven = (ModelDriven) action;
  18.  
  19. //获取值栈
  20.  
  21. ValueStack stack = invocation.getStack();
  22.  
  23. //调用 ModelDriven 接口的 getModel() 方法
  24.  
  25. //即调用 EmployeeAction 的 getModel() 方法
  26.  
  27. /*
  28.  
  29. public Employee getModel() {
  30.  
  31. employee = new Employee();
  32.  
  33. return employee;
  34.  
  35. }
  36.  
  37. */
  38.  
  39. Object model = modelDriven.getModel();
  40.  
  41. if (model != null) {
  42.  
  43. //把 getModel() 方法的返回值压入到值栈的栈顶. 实际压入的是 EmployeeAction 的 employee 成员变量
  44.  
  45. stack.push(model);
  46.  
  47. }
  48.  
  49. if (refreshModelBeforeResult) {
  50.  
  51. invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
  52.  
  53. }
  54.  
  55. }
  56.  
  57. 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拦截器主要源码:

  1. @Override
  2. public String doIntercept(ActionInvocation invocation) throws Exception {
  3. Object action = invocation.getAction();//获取当前执行的Action对象
  4. if (!(action instanceof NoParameters)) {//判断Action是否实现了NoParameters接口,实现该接口表示该Action没有任何请求参数
  5. ActionContext ac = invocation.getInvocationContext();//获取ActionContext对象
  6. final Map<String, Object> parameters = retrieveParameters(ac);//获取请求参数Map
  7. //省略...
  8. if (parameters != null) {//如果请求参数不为null
  9. Map<String, Object> contextMap = ac.getContextMap();//获取ActionContext内部的context Map,即OgnlContext对象
  10. try {
  11. //省略...
  12. ValueStack stack = ac.getValueStack();//获取值栈
  13. setParameters(action, stack, parameters);//为值栈设置参数
  14. } finally {
  15. //省略...
  16. }
  17. }
  18. }
  19. return invocation.invoke();//调用下一个拦截器
  20. }

可以知道为什么要实现自动赋值,只需要实现modelDriven接口就行了

其中最重要逻辑代码是setParometers()方法

  1. protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) {
  2. ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware)
  3. ? (ParameterNameAware) action : null;//判断Action有无实现ParameterNameAware接口
  4.  
  5. Map<String, Object> params;
  6. Map<String, Object> acceptableParameters;//合法参数集合
  7. //判断参数设置是否有序,ordered默认为false,即无序
  8. if (ordered) {
  9. params = new TreeMap<String, Object>(getOrderedComparator());//如果有序则要获取比较器
  10. acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());
  11. params.putAll(parameters);
  12. } else {
  13. params = new TreeMap<String, Object>(parameters);
  14. acceptableParameters = new TreeMap<String, Object>();
  15. }
  16. //迭代请求参数
  17. for (Map.Entry<String, Object> entry : params.entrySet()) {
  18. String name = entry.getKey();
  19. //判断参数是否合法,如果Action实现了ParameterNameAware则acceptableName(name)返回true且parameterNameAware.acceptableParameterName(name)
  20. //也返回true该参数才是合法的;如果Action没有实现ParameterNameAware则参数是否合法由acceptableName(name)方法决定
  21. boolean acceptableName = acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name));
  22. //如果参数合法
  23. if (acceptableName) {
  24. acceptableParameters.put(name, entry.getValue());//把合法参数添加到合法参数集合中
  25. }
  26. }
  27.  
  28. ValueStack newStack = valueStackFactory.createValueStack(stack);
  29. //省略...
  30. for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {//迭代合法参数
  31. String name = entry.getKey();//参数名
  32. Object value = entry.getValue();//参数值
  33. try {
  34. newStack.setValue(name, value);//将该参数设置到ValueStack中
  35. } catch (RuntimeException e) {
  36. //省略...
  37. }
  38. }
  39. //省略...
  40. //看该方法的名称是将合法参数添加到ActionContext中,但在该拦截器中,该方法为空实现,无任何代码
  41. //该方法被声明为protected,即子类可以覆盖该方法以改变行为
  42. addParametersToContext(ActionContext.getContext(), acceptableParameters);
  43. }

先判断提交过来的参数是否合法,因为提交过来的参数会影响到值栈所以struts2要对提交过来的参数进行合法性检查,以防止恶意用户的攻击,凡是请求参数中表达式中含有等号(=),逗号(,),#号(#)的都是非法表达式

至于怎么判断是否合法,我已经没兴趣了,知道是acceptableName(name)方法决定的。


了解了这么多感觉用的更随心所欲了。急需做无聊的毕业设计


关于struts2的modelDriven的更多相关文章

  1. 接触Struts2的ModelDriven<>接口

    最近在学SSH框架,实战项目,用到了Struts2的ModelDriven<>接口,在这做一点记录 ModelDriven,意为模型驱动,意思是直接把实体类当成页面数据的收集对象 参考他人 ...

  2. struts2重点——ModelDriven

    一.属性驱动 在目标 Action 类中,通过 setXxx() 方法来接收请求参数. 二.模型驱动 1.ParametersInterceptor 拦截器工作原理 ParametersInterce ...

  3. Struts2中ModelDriven的使用

    它是Struts2种独有的一种接收用户输入的机制,想在项目中使用模型驱动 (ModelDriven)需要让Action实现com.opensymphony.xwork2.ModelDriven 接口, ...

  4. Struts2 之 modelDriven & prepare 拦截器详解

    struts2 ModelDriven & Prepareable 拦截器 前面对于 Struts2 的开发环境的搭建.配置文件以及 Struts2 的值栈都已经进行过叙述了!这次博文我们讲解 ...

  5. Struts2之ModelDriven和Preparable拦截器

    首先struts.xml文件配置如下 默认拦截器设置为paramsPrepareParamsStack <package name="default" namespace=& ...

  6. struts2之ModelDriven的用法

    在Struts 2中,提供了另外一种直接使用领域对象的方式,就是让action实现com.opensymphony. xwork2.ModelDriven接口.ModelDriven让你可以直接操作应 ...

  7. Struts2之ModelDriven的使用

    http://www.cnblogs.com/luoyanli/archive/2012/11/20/2778361.html 我们可以根据Action属性的不同将它分为两类:Field-Driven ...

  8. struts2之ModelDriven

    在Struts 2中,提供了另外一种直接使用领域对象的方式,就是让action实现com.opensymphony. xwork2.ModelDriven接口.ModelDriven让你可以直接操作应 ...

  9. Struts2中ModelDriven的陷阱及其预防

    页面表单 <form action="updateInput.action" method="post"> <input type=" ...

随机推荐

  1. mvc JavaScriptResult的用法

    一.JavaScriptResult在MVC中的定义的代码片段   C# 代码   复制 public class JavaScriptResult : ActionResult { public o ...

  2. res/raw和assets的 区别

    res/raw和assets的相同点: 两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制. res/raw和assets的不同点: 1.res/raw中的文件会被映射到R.ja ...

  3. 线性模型(3):Logistic Regression

    此笔记源于台湾大学林轩田老师<机器学习基石><机器学习技法> (一)Logistic Regression 原理 对于分类问题,假设我们想得到的结果不是(x属于某一类)这种形式 ...

  4. 只有IE能上网,其他浏览器均不可以!

    今天起来,高高兴兴的来到实验室,发现电脑打开上不了网.本人平时喜欢用Chrome,发现上不了网,就开始ping.发现可以ping通,但是网页打不开! 第一反应是DNS的问题,可以发现DNS没问题,能正 ...

  5. Hbase Basic Prerequisites

    Table 2. Java HBase Version   JDK 6      JDK 7       JDK 8 1.0 Not     Supported yes Running with JD ...

  6. Components of the Impala Server

    Components of the Impala Server The Impala server is a distributed, massively parallel processing (M ...

  7. [Hive - LanguageManual] DML: Load, Insert, Update, Delete

    LanguageManual DML Hive Data Manipulation Language Hive Data Manipulation Language Loading files int ...

  8. Windows Server 2012 四个版本对比

    Windows Server 2012 有4种版本: Foundation, Essentials, Standard and Datacenter. 版本 Foundation Essentials ...

  9. the application could not be verified

    在iphone上安装app时,提示the application could not be verified 解决方式: 将iphone已有的这个app卸载,然后安装就可以了.

  10. Gym 100818I Olympic Parade(位运算)

    Olympic Parade http://acm.hust.edu.cn/vjudge/contest/view.action?cid=101594#problem/I [题意]: 给出N个数,找出 ...