您的位置:首页 > 编程语言 > Java开发

2014-07-20 Java Web的学习(17)-----struts2(3)----OGNL&ValueStack

2015-04-10 16:49 741 查看
body, td {
font-family: tahoma;
font-size: 10pt;
}

1.OGNL是什么?   OGNL就是表达式引擎,所谓表达式引擎就是处理View层和Controller层之间流转数据.在视图层,既没有数据类型的概念,也没有数据结构的概念.一旦对外展现,都会最终转化为同一的字符串形式.而Controller(Java)中存在各种数据类型的数据.这时就需要一整套的数据匹配规则.这种规则就是表达式引擎的最初定义的概念.它的作用就是帮助我们完成这种规则化的表达式与Java对象的相互转化.因而它成为架起MVC各个模块之间数据沟通的桥梁.  

     在Java世界中,有许多优秀的表达式引擎.OGNL引擎在其内部实现机制和设计原理上存在许多的亮点,因而Struts2选择了OGNL框架作为它依赖的表达式引擎,而且在OGNL的基础上做了一定程度的扩展.   

   OGNL(Object Graph Navigation Language)是一个开源的表达式引擎.通过OGNL,我们能够通过表达式存取Java对象树中的任意属性和调用对象Java树的方法。    所以说,OGNL就是语义字符串与Java对象之间沟通的催化剂.   2.OGNL API   
[align=left]/[/align] [align=left] The struts framework sets the OGNL context to be our ActionContext[/align] [align=left] and the value stack to be the OGNL root object.[/align] [align=left] (The value stack is a set of several objects[/align] [align=left]   but to OGNL it appears to be a single object.)[/align] [align=left] [align=left] [/align] [align=left] */[/align] [align=left][b]public class Ognl {[/align] [align=left]     /*[/align] [align=left]      通过传入OGNL表达式,在给定的上下文环境.从root对象中取值.[/align] [align=left]      OGNL不是Struts独有的.解决的问题是:web层弱类型和Java强类型的之间的转换.表达式引擎.[/align] [align=left]      [url=mailto:b>@param@param expression[/align] [align=left]      [url=mailto:b>@param@param context ------- ActionContext[/align] [align=left]      [url=mailto:b>@param@param root   ------ ValueStack (虽然是数据结构是栈.A Stack that is implemented using a List)[/align] [align=left]      [url=mailto:b>@return@return Object[/align] [align=left]      /[/align] [align=left]     public static Object getValue( String expression,Map context,Object root){[/align] [align=left]           return null;[/align] [align=left]     }[/align] [align=left]     /[/b][/align] [align=left]      通过传入OGNL表达式,在给定的上下文环境.向root对象中写值.[/align] [align=left]      [url=mailto:b>@param@param expression[/align] [align=left]      [url=mailto:b>@param@param context[/align] [align=left]      [url=mailto:b>@param@param root[/align] [align=left]      [url=mailto:b>@return@return Object[/align] [align=left]      /[/align] [align=left]     public static void setValue(String expression,Map context,Object root){[/align] [align=left]     }[/align] [align=left]}[/align]
通过上述代码可以发现:OGNL引擎主要干两件事情.取值和存值.而这些操作都必须传入三个参数.以后无论OGNL如何完成复杂的操作,都会映射到这三个参数,通过调用底层引擎完成相关计算.从而完成OGNL功能需要三个要素:
a.表达式(Expression),表达式会规定此次OGNL操作到底要干什么.
b.Root对象.可以理解为OGNL的操作对象.也就是"对谁干",Root对象实际上就是一个Java对象,在struts2中相对应的就是实现ValueStack接口的类OgnlValueStack对象中CompoundRoot root对象.(CompoundRoot类是一个有Java List集合构建的栈的结构,存放一组对象.下面在详细说).
The value stack is a set of several objects but to OGNL it appears to be a single object.
c.上下文环境(OgnlContext).有了表达式和Root对象.就已经可以使用OGNL的基本功能.不过,事实上在OGNL内部,所有的操作都会在一个特定的数据环境中运行,这个数据环境就是OGNL的上下文环境(Context)。说的明白一些,就是这个上下文环境规定OGNL的操作"在哪里干",OGNL的上下文环境就是Map结构.之前所提及的Root对象,也会被添加上下文环境中,并且被作为一个特殊的变量进行处理.在Struts2中就是ActionContext类实现的.
  3.OGNL的上下文环境(ActionContext)-----数据流体系(相互依存)  
public class ActionContext implements Serializable {
    //通过ThreadLocal设计模式,实现ActionContext一次访问中的数据共享.线程安全
    static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();     /
     Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}.
     /
    public static final String VALUE_STACK = ValueStack.VALUE_STACK;
    // [b]ActionContext中存储数据的上下文环境,ValueStack就存储其中,也有个名字叫做OgnlContext
    private Map<String, Object> context;
    /[/b]
     Stores a value in the current ActionContext. The value can be looked up using the key.
     @param key   the key of the value.
     @param value the value to be stored.
     /
    public void put(String key, Object value) {
        context.put(key, value);
    }
    /*
     Returns a value that is stored in the current ActionContext by doing a lookup using the value's key.
    
     @param key the key used to find the value.
     @return the value that was found using the key or <tt>null</tt> if the key was not found.
     /
    public Object get(String key) {
        return context.get(key);
    }
    /
     Sets the OGNL value stack.
     设置ValueStack
     @param stack the OGNL value stack.
     /
    public void setValueStack(ValueStack stack) {
        put(VALUE_STACK, stack);
    }
    /

     Gets the OGNL value stack.
     获取ValueStack
     @return the OGNL value stack.
     /
    public ValueStack getValueStack() {
        return (ValueStack) get(VALUE_STACK);
    }
}
从上面源码可以得出: 1.ActionContext
  ActionContext是XWork中最重要的概念之一.它提供整个Xwork时间处理的上下文环境,在这个数据环境包含了所有事件处理过程中所需要的数据对象.所以每一个事件响应,都有一个ActionContext对象的存在与之对应.
2.从源码中,我们可以看到ActionContext真正的数据存储空间,是位于其中Map类型的变量context.ActionContext将所有的数据对象以特定的key值存放在context之中.而ActionContext也提供获取重要元素的快捷方法:如getValueStack,getSession; 
3.如何保证线程安全的:ThreadLocal设计模式
4.ActionContext所提供的数据的访问返回的都是Map类型的数据对象,而不是真正的HttpSession等这样纯正的Web容器对象.做到与Web容器无关.
  好处:原生的web容器对象的本身不是线程安全的.而通过Xwork的封装。彻底消除这一隐患.
      保持所有存储对象的Map结构,可以统一数据访问方式.       [url=http://static.oschina.net/uploads/img/201504/10164909_CLnY.png]


  ps:ActionContext-------SerlverActionContext,struts2提供一个子类继承ActionContext的,与Web容器打交道的方案. 5.当Struts2接受一个请求时.会迅速创建ActionContext对象,ValueStack对象,action对象,然后把action实例对象(UserAction{name,password})存放进ValueStack,所以action的实例变量可以被OGNL访问. 6.ActionContext类中成员变量Map<String,Object> context的结构图:                 

   如果需要访问上下文的对象需要#符号标注命名空间,如#application,#session,#request.注意:需要配合struts2的标签一起使用.    另外的话OGNL会设定一个根对象(root对象),在struts2中就是OgnlVauleStack(值栈,是一个list集合).如果要访问根对象中对象的属性.则可以忽略#命名空间,直接访问该对象的属性即可.如如果UserAction对象(存在name属性)在值栈中的话,就可以直接<s:property value="name">.至于值栈是什么样的查询规则而又为什么不需要#命名空间?.下面详解:
  4.ValueStack以及其实现类OgnlValueStack-----对OGNL的扩展
 
ValueStatck是针对OGNL计算的扩展,实际上就是针对OGNL三要素中Root对象所进行的扩展.使得在Struts2在使用ValueStack进行OGNL、计算时,可以将一组对象都视为Root对象.
                 

OgnlValueStack类的源代码:
public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
     //使用装饰模式,将根元素(栈结构)封装在ValueStack对象内容.
     //从外界来看,所有的操作就像针对单一对象的操作.实际在内部,是List形成的栈结构.
     CompoundRoot root;      //OnglContext对象 [align=left]     transient Map<String, Object> context;  [/align]      //构造函数,这里讲制定OGNL计算所需的参数
     protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticAccess) {
        //调用setRoot方法完成初始化
        setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticAccess);
    }
    //真正的OgnlValueStack的初始化过程.
    protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot,
                           boolean allowStaticMethodAccess) {
        //根对象是一个CompoundRoot类型的栈结构
        this.root = compoundRoot;
        this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess);
        //创建OGNL的上下文
        this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess);
        //设置OGNL上下文的其他相关参数
        context.put(VALUE_STACK, this);
        Ognl.setClassResolver(context, accessor);
        ((OgnlContext) context).setTraceEvaluations(false);
        ((OgnlContext) context).setKeepLastEvaluation(false);
    }
}
 
OgnlValueStack使用了一个典型的装饰模式,真正的其内部起到核心作用的是一个叫做CompoundRoot root的数据结构,可以存储多个对象(栈结构).ValueStack是一个被设计成"栈"的数据结构.并且还是一个具备表达式引擎计算能力的数据结构.OGNL与Stack的结合.
 
/*
A Stack that is implemented using a List.
@author plightbo
@version $Revision: 894090 $
*/
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);
    }
}
 

 








内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: