struts2对Ognl的封装--root对象

 

root 对象  

     CompoundRoot, CompoundRoot扩展了ArrayList,具有容纳对象及后进先出类似“栈”的能力。

 

  

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);
    }
}

(不明白为啥用0做栈顶呢?ArrayList 每次push 或remove 之后都需要重建数组)

 

CompoundRoot中元素的添加及提取:

OgnlValueStack提供的peek,pop,push 方法,从root中提取元素或添加元素: 

Java代码 
  1. /** 
  2.  * @see com.opensymphony.xwork2.util.ValueStack#peek() 
  3.  */  
  4. public Object peek() {  
  5.     return root.peek();  
  6. }  
  7.   
  8. /** 
  9.  * @see com.opensymphony.xwork2.util.ValueStack#pop() 
  10.  */  
  11. public Object pop() {  
  12.     return root.pop();  
  13. }  
  14.   
  15. /** 
  16.  * @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object) 
  17.  */  
  18. public void push(Object o) {  
  19.     root.push(o);  
  20. }  

  

通过表达式对CompoundRoot中元素的访问

 

CompoundRootAccessor 实现了 CompoundRoot 中元素以表达式方式的访问,

CompoundRootAccessor类扩展了ognl的PropertyAccessor,MethodAccessor,ClassResolver

 


struts2对Ognl的封装--root对象_第1张图片

Ognl中的root对象一般是一个javabean或Map,通过表达式中指定的属性名或key,就可以定位到属性对象

 CompoundRoot 是一个ArrayList,对于表达式中指定的属性,是ArrayList中哪一个元素的属性呢? 这就需要遍历每一个元素,进行判断。

 

  

以表达式方式对CompoundRoot  中元素的属性赋值(setProperty):

  对 CompoundRoot  遍历遍历顺序由栈顶到栈底,遍历的每一个元素,都当做ognl的root对象,判断是否存在指定的属性,如果存在则对该root对象的属性赋值,遍历中下一个元素是Map,则直接使用put 方法存属性和名称,就不继续查找了:

        for (Object o : root) {//CompoudRoot是ArrayList,遍历内部所有对象
            if (o == null) {
                continue;
            }

            try {
                if (OgnlRuntime.hasSetProperty(ognlContext, o, name)) {
                    OgnlRuntime.setProperty(ognlContext, o, name, value);
                    //当前元素有name属性,则调用ognl进行赋值
                    return;
                } else if (o instanceof Map) {
                    Map<Object, Object> map = (Map) o;
                    try {
                        map.put(name, value);
                        return;//如果下一个元素是Map,则直接使用put方法存属性名和值
                    } catch (UnsupportedOperationException e) {
                        // This is an unmodifiable Map, so move on to the next element in the stack
                    }
                }
}

  

以表达式方式对CompoundRoot  中元素的属性值的获值(getProperty):

  对 CompoundRoot  遍历遍历顺序由栈顶到栈底,遍历的每一个元素,都当做ognl的root对象,判断是否存在指定的属性,如果存在则获值属性值:

 

            for (Object o : root) {//遍历
                if (o == null) {
                    continue;
                }

                try {
                    if ((OgnlRuntime.hasGetProperty(ognlContext, o, name)) || ((o instanceof Map) && ((Map) o).containsKey(name))) {
                        return OgnlRuntime.getProperty(ognlContext, o, name);//当前元素有该属性,则获取
                    }
                } catch (OgnlException e) {
                    if (e.getReason() != null) {
                        final String msg = "Caught an Ognl exception while getting property " + name;
                        throw new XWorkException(msg, e);
                    }
                } catch (IntrospectionException e) {
                    // this is OK if this happens, we'll just keep trying the next
                }
            }

 

以表达式方式对CompoundRoot  中元素的方法调用(callMethod):

  对 CompoundRoot  遍历遍历顺序由栈顶到栈底,遍历的每一个元素,都当做ognl的root对象,对其调用指定的方法,如果返回值不为空,则说明正确,并返回方法返回值。

 

 

        for (Object o : root) {//遍历
            if (o == null) {
                continue;
            }

            Class clazz = o.getClass();
            Class[] argTypes = getArgTypes(objects);

            MethodCall mc = null;

            if (argTypes != null) {
                mc = new MethodCall(clazz, name, argTypes);
            }

            if ((argTypes == null) || !invalidMethods.containsKey(mc)) {
                try {
                    Object value = OgnlRuntime.callMethod((OgnlContext) context, o, name, name, objects);

                    if (value != null) {//返回值不为空,该元素上有此方法并调用成功
                        return value;
                    }
                } catch (OgnlException e) {
                    // try the next one
                    Throwable reason = e.getReason();

                    if (!context.containsKey(OgnlValueStack.THROW_EXCEPTION_ON_FAILURE) && (mc != null) && (reason != null) && (reason.getClass() == NoSuchMethodException.class)) {
                        invalidMethods.put(mc, Boolean.TRUE);
                    } else if (reason != null) {
                        throw new MethodFailedException(o, name, e.getReason());
                    }
                }
            }
        }

 

对 CompoundRoot    指定位置元素的访问:

1.top.属性名 (top 栈顶元素)

2.[index].top  CompoundRoot    中的第N个元素[index]会调用 CompoundRoot.cutStack从第indedx位置开始的元素组成新的 CompoundRoot,top是栈顶元素

 

你可能感兴趣的:(struts2)