struts2对Ognl的打包-OgnlValueStack

struts2对Ognl的封装--OgnlValueStack

Ognl的扩展点:

http://java12345678.iteye.com/blog/2031790

 

 

 类OgnlValueStack 是struts2对Ognl的封装,提供了表达式取值或赋值方法,并不像ognl那样需要在方法参数中传递context,root 对象,因为context 、root对象已封状在OgnlValueStack 内部

 



struts2对Ognl的打包-OgnlValueStack

Struts 对Ognl的封装,提供了setValue、set、setParameter等方法通过表达式赋值,findValue,findString 等方法取值。

构建器调用setRoot方法构建OgnlValueStack对象,并生成Ognl需要的相关对象:

    protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot,
                           boolean allowStaticMethodAccess) {
        this.root = compoundRoot;
        this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess);
        this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess);
        context.put(VALUE_STACK, this);
        Ognl.setClassResolver(context, accessor);
        ((OgnlContext) context).setTraceEvaluations(false);
        ((OgnlContext) context).setKeepLastEvaluation(false);
    }

 

 

1.ognl上下文:Map<String,Object> contex

this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess);

 

2. ognl的root对象:CompoundRoot root=CompoundRoot :,表达式从中取值或赋值       

 

3:MemeberAccess: ognl的成员是否可以访问(SecurityMemberAccess)

  this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess);

 

4.ognl的ClassResolver(用于加载类)(CompoundRootAccessor)

   Ognl.setClassResolver(context, CompoundRootAccessor);

 

5.ognl的TypeConverter 用于类型转换(new OgnlTypeConverterWrapper(XWorkConverter))   

          

6.PropertyAccessor

  由工厂ValueStackFactory生成实例时,注入Container时,调用OgnlRuntime.setPropertyAccessor

7.MethodAccessor

由工厂ValueStackFactory生成实例时,注入Container时,调用OgnlRuntime.setMethodAccessor

 8.NullHandler

 由工厂ValueStackFactory生成实例时,注入Container时,调用OgnlRuntime.setNullHandler

 

ValueStackFactory类的方法:

    @Inject
    public void setContainer(Container container) throws ClassNotFoundException {
        Set<String> names = container.getInstanceNames(PropertyAccessor.class);
        for (String name : names) {
            Class cls = Class.forName(name);
            if (cls != null) {
                if (Map.class.isAssignableFrom(cls)) {
                    PropertyAccessor acc = container.getInstance(PropertyAccessor.class, name);
                }
                OgnlRuntime.setPropertyAccessor(cls, container.getInstance(PropertyAccessor.class, name));
                if (compoundRootAccessor == null && CompoundRoot.class.isAssignableFrom(cls)) {
                    compoundRootAccessor = (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, name);
                }
            }
        }

        names = container.getInstanceNames(MethodAccessor.class);
        for (String name : names) {
            Class cls = Class.forName(name);
            if (cls != null) {
                OgnlRuntime.setMethodAccessor(cls, container.getInstance(MethodAccessor.class, name));
            }
        }

        names = container.getInstanceNames(NullHandler.class);
        for (String name : names) {
            Class cls = Class.forName(name);
            if (cls != null) {
                OgnlRuntime.setNullHandler(cls, new OgnlNullHandlerWrapper(container.getInstance(NullHandler.class, name)));
            }
        }
        if (compoundRootAccessor == null) {
            throw new IllegalStateException("Couldn't find the compound root accessor");
        }
        this.container = container;
    }
}

 

 

 

OgnlValueStack提供的findxxx方法,通过表达式取值,都会调用如下:

 

 private Object tryFindValue(String expr) throws OgnlException {
        Object value;
        if (defaultType != null) {
            value = findValue(expr, defaultType);
        } else {
            value = getValueUsingOgnl(expr);
            if (value == null) {//在ognl中没有找到
                value = findInContext(expr);//到上下文中查找
            }
        }
        return value;
    }

/**
*使用Ognl获取表达式的值 参数contxt上下文,root对象
**/
 private Object getValueUsingOgnl(String expr) throws OgnlException {
        try {
            return ognlUtil.getValue(expr, context, root);
        } finally {
            context.remove(THROW_EXCEPTION_ON_FAILURE);
        }
    }
/**
* ognlUtil类中的方法
* 使用Ognl获取表达式的值
*/
 public Object getValue(String name, Map<String, Object> context, Object root) throws OgnlException {
        return Ognl.getValue(compile(name, context), context, root);
    }
/**
*从上下文的Map对象中直接get
*/
 private Object findInContext(String name) {
        return getContext().get(name);
    }
 
  OgnlValueStack提供的setParameter和setValue方法,通过表达式赋值,都会调用如下:
 private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Map<String, Object> context, boolean evalExpression) throws OgnlException {
        context.put(XWorkConverter.CONVERSION_PROPERTY_FULLNAME, expr);
        context.put(REPORT_ERRORS_ON_NO_PROP, (throwExceptionOnFailure) ? Boolean.TRUE : Boolean.FALSE);
        ognlUtil.setValue(expr, context, root, value, evalExpression);
//调用ognl赋值,并传递context,root对象
    }
/**
*调用ognl赋值
*/
 protected void setValue(String name, Map<String, Object> context, Object root, Object value, boolean evalName) throws OgnlException {
        Object tree = compile(name, context);
        if (!evalName && isEvalExpression(tree, context)) {
            throw new OgnlException("Eval expression cannot be used as parameter name");
        }
        Ognl.setValue(tree, context, root, value);
    }
 

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

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#peek()
     */
    public Object peek() {
        return root.peek();
    }

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#pop()
     */
    public Object pop() {
        return root.pop();
    }

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object)
     */
    public void push(Object o) {
        root.push(o);
    }