zoukankan      html  css  js  c++  java
  • 关于struts2的modelDriven


    今天做毕业设计,前台往后台赋值,习惯性的用了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)方法决定的。


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


    欲为大树,何与草争;心若不动,风又奈何。
  • 相关阅读:
    poj 1860 Currency Exchange(最短路径的应用)
    poj 2965 The Pilots Brothers' refrigerator
    zoj 1827 the game of 31 (有限制的博弈论)
    poj 3295 Tautology (构造法)
    poj 1753 Flip Game(枚举)
    poj 2109 (贪心)
    poj 1328(贪心)
    Qt 对单个控件美化
    Qt 4基础
    Bash Shell
  • 原文地址:https://www.cnblogs.com/admln/p/aboutStruts2ModelDriven.html
Copyright © 2011-2022 走看看