• OGNL介绍


    OGNL介绍:
    OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。这样可以更好的取得数据。
    OGNL可以让我们用非常简单的表达式访问对象层,例如,当前环境的根对象为user1,则表达式person.address[0].province可以访问到user1的person属性的第一个address的province属性。
    这种功能是模板语言的一个重要补充,像jsp2.0,velocity,jelly等等,都有类似的功能,但是ognl比它们完善得多,而且以一个独立的lib出现,方便我们构建自己的框架。
    表达式:
    OGNL支持各种纷繁复杂的表达式。但是最最基本的表达式的原型,是将对象的引用值用点串联起来,从左到右,每一次表达式计算返回的结果成为当前对象,后面部分接着在当前对象上进行计算,一直到全部表达式计算完成,返回最后得到的对象。OGNL则针对这条基本原则进行不断的扩充,从而使之支持对象树、数组、容器的访问,甚至是类似SQL中的投影选择等操作。
    1. 基本对象树的访问
    对象树的访问就是通过使用点号将对象的引用串联起来进行。
    例如:xxxx,xxxx.xxxx,xxxx. xxxx. xxxx. xxxx. xxxx
    2. 对容器变量的访问
    对容器变量的访问,通过#符号加上表达式进行。
    例如:#xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx
    3. 使用操作符号
    OGNL表达式中能使用的操作符基本跟Java里的操作符一样,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外,还能使用 mod, in, not in等。
    4. 容器、数组、对象
    OGNL支持对数组和ArrayList等容器的顺序访问:例如:group.users[0]
    同时,OGNL支持对Map的按键值查找:
    例如:#session['mySessionPropKey']
    不仅如此,OGNL还支持容器的构造的表达式:
    例如:{"green", "red", "blue"}构造一个List,#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}构造一个Map
    你也可以通过任意类对象的构造函数进行对象新建:
    例如:new Java.net.URL("xxxxxx/")
    5. 对静态方法或变量的访问
    要引用类的静态方法和字段,他们的表达方式是一样的@class@member或者@class@method(args):
    例如:@com.javaeye.core.Resource@ENABLE,@com.javaeye.core.Resource@getAllResources
    6. 方法调用
    直接通过类似Java的方法调用方式进行,你甚至可以传递参数:
    例如:user.getName(),group.users.size(),group.containsUser(#requestUser)
    7. 投影和选择
    OGNL支持类似数据库中的投影(projection) 和选择(selection)。
    投影就是选出集合中每个元素的相同属性组成新的集合,类似于关系数据库的字段操作。投影操作语法为 collection.{XXX},其中XXX 是这个集合中每个元素的公共属性。
    例如:group.userList.{username}将获得某个group中的所有user的name的列表。
    选择就是过滤满足selection 条件的集合元素,类似于关系数据库的纪录操作。选择操作的语法为:collection.{X YYY},其中X 是一个选择操作符,后面则是选择用的逻辑表达式。而选择操作符有三种:
    ? 选择满足条件的所有元素
    ^ 选择满足条件的第一个元素
    $ 选择满足条件的最后一个元素
    例如:group.userList.{? #txxx.xxx != null}将获得某个group中user的name不为空的user的列表。
     

    Ognl其实就是Map,它又分为一个根对象(Root)和多个非根对象
    非根对象要通过"#key"访问,根对象可以省略"#key"
    比如我们获取一个为根对象的的对象的属性,就只需要直接根据属性名就好了:String employeeName = (String) OnglExpression.getValue(“name”, ctx, e);
    如果不是根对象: String managerName (String)OnglExpression.getValue("#manager.name",ctx, e);

    对象取值和非根对象取值的现象,以及OGNL取值和赋值的案例

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

    OGNL向ValueStack压栈

    后台定义属性和实现modelDriver接口,提供get和set方法

     1 private HttpServletRequest req;
     2     private Cal cal1=new Cal();
     3     private Cal cal2;
     4     private String sex;
     5     private String num1;
     6     
     7     
     8     public String getNum1() {
     9         return num1;
    10     }
    11 
    12 
    13     public void setNum1(String num1) {
    14         this.num1 = num1;
    15     }
    16 
    17 
    18     public Cal getCal2() {
    19         return cal2;
    20     }
    21 
    22 
    23     public void setCal2(Cal cal2) {
    24         this.cal2 = cal2;
    25     }
    26 
    27 
    28     public String getSex() {
    29         return sex;
    30     }
    31 
    32 
    33     public void setSex(String sex) {
    34         this.sex = sex;
    35     }
    36     
    37     /**
    38      * implements ModelDriven
    39      * @return
    40      */
    41     public String accept1() {
    42         System.out.println("cal1:"+cal1);
    43         System.out.println("num1:"+num1);
    44         return "rs";
    45     }

    运行显示cal1.num1有值,而num1却取不到值

    这就和ValueStack的压栈有关系了,压栈的结构是先进后出,而ValueStack的取值是取到了值就会返回,不会往下取了。
    而ValueStack对取值的压栈是先把xxxAction也就是我们通过set和get方法取值的方式先压入栈底,然后再把ModelDriver压入,所有会先取到通过ModelDriver来获取值的,而获取到了就返回了,导致后面的值不会获取了。

  • 相关阅读:
    react项目建立导入包问题总结
    React中创建组件的3种方式
    export default与export的区别
    vue中的过滤器
    git clone https://chromium.googlesource.com/失败
    typescript 实现函数重载
    Rename a local and remote branch in git
    使用typescript开发react应用
    自己实现一个Promise库
    【翻译】Webpack 4 从0配置到生产模式
  • 原文地址:https://www.cnblogs.com/AluoKa/p/11104625.html
Copyright © 2020-2023  润新知