ONGL简介:

  OGNL 的全称是对象图导航语言( Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存储 java 对象的任意属性,调用 java 对象的方法,同时能够自动实现必要的类型转换。如果把表达式看作是一种带有语义的字符串,那么 OGNL 无疑成为了这个语义字符串于 java 对象之间的沟通桥梁。
  

        OGNL的要素

    表达式:表达式是整个OGNL的核心,OGNL会根据表达式去对象中取值,所有的OGNL操作都是指对表达式解析后进行的。它表明了此次OGNL操作要做什么。表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容。OGNL支持大量的表达式语法,不仅支持这种“链式”对象访问路径,还支持在表达式中进行简单的计算。

    根对象(ROOT):Root对象可以理解为OGNL的操作对象,表达式规定了“做什么”,而Root对象则规定了“对谁操作"。OGNL称为对象图导航语言,所谓对象图,就是以任意对象为根,通过OGNL可以访问这个对象关联的其他。

    Context对象:实际上OGNL的取值还需一个上下文环境,设置了Root对象,OGNL可以对root对象进行取值或者写值等操作,root对象所在环境就是OGNL的上下文环境(Context)。上下文环境规定了OGNL的操作”在哪里进行“。上下文环境COntext是一个map类型的对象,在表达式中访问Context中的对象,需要使用”#”号加上对象名称,即“#对象名称”的形式。

  OGNL的取值与赋值方法

 1 /**
 2  * 用于OGNL表达计算的一个工具类
 3  * 
 4  */
 5 public class OnglExpression {
 6     private OnglExpression() {
 7     }
 8 
 9     /**
10      * 根据OGNL表达式进行取值操作
11      * 
12      * @param expression
13      *            ognl表达式
14      * @param ctx
15      *            ognl上下文      map
16      * @param rootObject
17      *            ognl根对象
18      * @return
19      */
20     public static Object getValue(String expression, OgnlContext ctx,
21             Object rootObject) {
22 //            ${book.c.name} 意味着你要在jsp上获取书籍的类别的名称  ctx.get(#name)  根对象取值
23 //            ctx.get(${book.c.name})   非根对象取值
24         try {
25             return Ognl.getValue(expression, ctx, rootObject);
26         } catch (OgnlException e) {
27             throw new RuntimeException(e);
28         }
29     }
30 
31     /**
32      * 根据OGNL表达式进行赋值操作
33      * 
34      * @param expression
35      *            ognl表达式
36      * @param ctx
37      *            ognl上下文
38      * @param rootObject
39      *            ognl根对象
40      * @param value
41      *            值对象
42      */
43     public static void setValue(String expression, OgnlContext ctx,
44             Object rootObject, Object value) {
45         try {
46             Ognl.setValue(expression, ctx, rootObject, value);
47         } catch (OgnlException e) {
48             throw new RuntimeException(e);
49         }
50     }
51 }

  EL表达式和OGNL的区别:

OGNL表达式只对struts标签管用,在HTML标签中还是要使用EL表达式
struts2标签中都是用的OGNL表达式,先从栈顶找,找不到就从map域中找,再找不到直接报错
而常规EL表达式只能从map域中找,不能在栈顶找,找不到什么都不显示。
搜索顺序为:page>request>session>application
但是struts2对HttpRequest对象进行了封装StrutsRequestWrapper,此时EL表达式可以在栈顶搜索
搜索顺序为:page>request>ValueStack>session>application

  OGNL的取值与赋值案列

 1 public class Demo1 {
 2 
 3     /**
 4      * @param args
 5      * @throws OgnlException
 6      */
 7     public static void main(String[] args)  {
 8 //        叫小李的员工
 9         Employee e = new Employee();
10         e.setName("小李");
11 //         张经理的管理
12         Manager m = new Manager();
13         m.setName("张经理");
14 
15         // 创建OGNL下文,而OGNL上下文实际上就是一个Map对象
16         OgnlContext ctx = new OgnlContext();
17 
18         // 将员工和经理放到OGNL上下文当中去
19         ctx.put("employee", e);
20         ctx.put("manager", m);
21 //        小李是根对象   一个公司有很多老板   只有一个员工小李
22         ctx.setRoot(e);// 设置OGNL上下文的根对象  
23 
24         /** ********************** 取值操作 *************************** */
25         // 表达式name将执行e.getName(),因为e对象是根对象(请注意根对象和非根对象表达式的区别)
26         String employeeName = (String) OnglExpression.getValue("name", ctx, e);
27         System.out.println(employeeName); //小李
28 
29         // 表达式#manager.name将执行m.getName(),注意:如果访问的不是根对象那么必须在前面加上一个名称空间,例如:#manager.name
30         String managerName = (String) OnglExpression.getValue("#manager.name",
31                 ctx, e);
32         System.out.println(managerName);  //张经理
33 
34         // 当然根对象也可以使用#employee.name表达式进行访问
35         employeeName = (String) OnglExpression.getValue("#employee.name", ctx,
36                 e);
37         System.out.println(employeeName);  //小李
38 
39         /** ********************** 赋值操作 *************************** */
40         OnglExpression.setValue("name", ctx, e, "小明");
41         employeeName = (String) OnglExpression.getValue("name", ctx, e);
42         System.out.println(employeeName);  //小明
43 
44         OnglExpression.setValue("#manager.name", ctx, e, "孙经理");
45         managerName = (String) OnglExpression.getValue("#manager.name", ctx, e);
46         System.out.println(managerName);  //孙经理
47 
48         OnglExpression.setValue("#employee.name", ctx, e, "小芳");
49         employeeName = (String) OnglExpression.getValue("name", ctx, e);
50         System.out.println(employeeName);  //小芳
51     }
52 }

  输出结果:

  OGNL在struts2中的应用

    public String test1() {
//        ValueStack是一个堆栈结构的容器  有压栈操作   先进后出
        ValueStack vs = ServletActionContext.getContext().getValueStack();
        vs.push(new Employee("张雇员", 2000));// 1
        vs.push(new Student("小明同学", "s001"));// 0
        System.out.println(vs.findValue("name"));  //小明
        System.out.println(vs.findValue("salary"));  //2000
        return "rs";
    }

  配置文件设置:

        <action name="/stack_*" class="com.liuwenwu.test.DemoAction" method="{1}">
            <result name="rs">/rs.jsp</result>
        </action>

 

  jsp代码:

<a href="${pageContext.request.contextPath }/sy/stack_test1.action?sex=nv">ognl1</a>

  输出结果:

  证明ValueStack是一个堆栈结构的容器  有压栈操作   先进后出

valueStack的赋值套路

  

    private Cal cal1=new Cal();

    private String num1;

    public String getNum1() {
        return num1;
    }

    public void setNum1(String num1) {
        this.num1 = num1;
    }

    public String accept1() {
//        cal使用的是ModelDriven赋值
        System.out.println("cal1:"+cal1);
//        num使用的是get/set赋值
        System.out.println("num1:"+num1);

        return "rs";    
    }

  jsp代码:

<a href="${pageContext.request.contextPath }/sy/demo_accept1.action?num1=20&&num2=5">accept1</a>

  输出结果:

cal1有值而num1没值  cal1通过ModelDriven接口赋值 num1通过get/set方法赋值  最终压栈的结构 num1在下  cal1在上  所以赋值在cal1上 不会赋值到底部的num1上 所以num1为 null

 

posted on 2019-06-28 20:36  骑猪南下L  阅读(144)  评论(0编辑  收藏  举报