• OGNL表达式


    在学习Struts2中的OGNL和值栈的时候,遇到了OGNL,看了一些后还是发下对这个OGNL 完全模糊,在此节单独对OGNL进行学习。

    目的是学完后知道OGNL是来干嘛的?可以怎么使用。

    OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。 ——百度百科

    OGNL我们看到最多的就是和Struts2的标签结合使用,但其实OGNL离开了Struts2也是可以的,只是用在Struts2中,就必须和标签库结合才能使用。

    这篇文章就先讲讲OGNL不结合Struts2的一些用法,下篇文章再讲OGNL在Struts2中的用法。

    1.OgnlContext类和Ognl类的介绍

    在类中使用OGNL表达式,和两个类息息相关,分别是OgnlContext类和Ognl类。

    Ognl类:This class provides static methods for parsing and interpreting OGNL expressions.根据官方解释,这个类是提供一些静态方法去解析表达式。

    OgnlContext:This class defines the execution context for an OGNL expression.该类定义OGNL表达式的执行上下文。

    public class OgnlContext extends Object implements Map {}

    OgnlContext类实现了Map接口,所以它也是一个Map,可以通过put方法往该上下文环境中放元素。该上下文环境中,有两种对象:根对象和普通对象。我们可以使用它的setRoot方法设置根对象。根对象只能有一个,而普通对象则可以有多个。因为它实现了java.utils.Map 的接口。OgnlContext(ognl上下文)=根对象(1个)+非根对象(n个),非根对象要通过"#key"访问,根对象可以省略"#key"。

    2.Ognl获取普通对象和根对象的方法

    在上下文环境中,有根对象和普通的对象,两者的获取方式有所不同:获取根对象的属性值,可以直接使用属性名作为表达式,也可以使用#对象名.属性名的方式;获取普通对象的属性值,则必须使用#对象名.属性名的方式获取。(可以将普通对象设置为根对象,但只能有一个根对象,后面设置的根对象会覆盖前面的根对象)下面举例说明。

      1 package OGNL;
      2 
      3 import java.util.List;
      4 
      5 public class School {
      6     
      7     private String name;
      8     private List<Teacher> teachers;
      9     
     10     
     11     public School() {
     12         super();
     13     }
     14     
     15     
     16     public School(String name, List<Teacher> teachers) {
     17         super();
     18         this.name = name;
     19         this.teachers = teachers;
     20     }
     21 
     22 
     23     /**
     24      * @return the name
     25      */
     26     public String getName() {
     27         return name;
     28     }
     29     /**
     30      * @param name the name to set
     31      */
     32     public void setName(String name) {
     33         this.name = name;
     34     }
     35     /**
     36      * @return the teachers
     37      */
     38     public List<Teacher> getTeachers() {
     39         return teachers;
     40     }
     41     /**
     42      * @param teachers the teachers to set
     43      */
     44     public void setTeachers(List<Teacher> teachers) {
     45         this.teachers = teachers;
     46     }    
     47     
     48 
     49 }
     50 
     51 package OGNL;
     52 
     53 public class Teacher {
     54     
     55     private String name;
     56     private String gender;
     57     private int age;    
     58     
     59     
     60     public Teacher() {
     61         super();
     62     }
     63     
     64     public Teacher(String name, String gender, int age) {
     65         super();
     66         this.name = name;
     67         this.gender = gender;
     68         this.age = age;
     69     }
     70     /**
     71      * @return the name
     72      */
     73     public String getName() {
     74         return name;
     75     }
     76     /**
     77      * @param name the name to set
     78      */
     79     public void setName(String name) {
     80         this.name = name;
     81     }
     82     /**
     83      * @return the gender
     84      */
     85     public String getGender() {
     86         return gender;
     87     }
     88     /**
     89      * @param gender the gender to set
     90      */
     91     public void setGender(String gender) {
     92         this.gender = gender;
     93     }
     94     /**
     95      * @return the age
     96      */
     97     public int getAge() {
     98         return age;
     99     }
    100     /**
    101      * @param age the age to set
    102      */
    103     public void setAge(int age) {
    104         this.age = age;
    105     }        
    106 
    107 }
    108 
    109 package OGNL;
    110 
    111 import java.util.ArrayList;
    112 import java.util.List;
    113 
    114 import ognl.Ognl;
    115 import ognl.OgnlContext;
    116 import ognl.OgnlException;
    117 
    118 public class Test {
    119     
    120     public static void main(String args[]) throws OgnlException{
    121         
    122         //定义一个老师对象
    123         Teacher t1 = new Teacher("zhangsan","男",30);        
    124         List<Teacher> teachers =new ArrayList<Teacher>();
    125         teachers.add(t1);
    126         
    127         //定义一个学校对象
    128         School sc = new School("China", teachers);
    129         
    130         //创建一个OgnlContext对象
    131         OgnlContext context  = new OgnlContext();
    132         
    133         //将老师和学校放入上下文环境中
    134         context.put("t1", t1);
    135         context.put("sc", sc);
    136         
    137         //未设置根对象之前,根对象为null
    138         System.out.println("0000:"+context.getRoot());
    139         
    140         //设置学校为根对象
    141         context.setRoot(sc);
    142         System.out.println("1111:"+context.getRoot());
    143         //若继续设置根对象,会覆盖前面的根对象
    144         //context.setRoot(t1);
    145         
    146         //获取根对象属性
    147         //获取根对象的属性值,可以直接使用属性名作为表达式,也可以使用#对象名.属性名的方式;
    148         Object expression = Ognl.parseExpression("name");
    149         //Object expression = Ognl.parseExpression("#sc.name");
    150         
    151         Object result = Ognl.getValue(expression, context, context.getRoot());
    152         // 获取根对象的信息,使用#获取上下文中的属性值时,必须使用带Map context参数getValue方法,指定上下文环境
    153         // 获取根对象的信息,直接获取,没有使用#,则可以使用不带Map context参数getValue方法
    154         Object result1 = Ognl.getValue(expression, context.getRoot());
    155         System.out.println("2222:"+result);
    156         System.out.println("2222:"+result1);
    157         
    158         //获取普通对象的属性值,则必须使用#对象名.属性名的方式获取
    159         expression = Ognl.parseExpression("#t1.name");
    160         result = Ognl.getValue(expression, context, context.getRoot());
    161         System.out.println("3333:"+result);
    162     }
    163 
    164 }

    运行测试代码:这种方法通过属性来获取属性值

    0000:null
    1111:OGNL.School@11028347
    2222:China
    2222:China
    3333:zhangsan

    总结:

    1.根对象只能有一个,当你尝试设置多个的时候,后面的会覆盖前面的。
    2.访问根对象中的属性,可以直接使用属性名,或者#对象名.属性名,但不能使用对象名.属性名,不然它会认为这是根对象中的一个属性叫对象名,然后访问这个属性的名叫属性名的属性值。

    3.不使用#获取根对象中的属性值时, 使用getValue方法可以不指定上下文环境,因为第三个参数已经得到了根对象,它指定去根对象中找。如果获取普通对象的属性,则必须在getValue方法中指定上下文环境,因为你不知道它找不到。
    4.通过根对象间接获取普通对象的属性时,比如List集合,使用下标去获取

    3.Ognl访问非静态方法、静态方法、静态字段的方法

    Ognl不但可以访问我们自己定义的类的属性和方法,还可以访问Java API中的静态方法和静态字段。

     1 package OGNL;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 import ognl.Ognl;
     7 import ognl.OgnlContext;
     8 import ognl.OgnlException;
     9 
    10 public class Test {
    11     
    12     public static void main(String args[]) throws OgnlException{
    13         
    14         //定义一个老师对象
    15         Teacher t1 = new Teacher("zhangsan","男",30);        
    16         List<Teacher> teachers =new ArrayList<Teacher>();
    17         teachers.add(t1);
    18         
    19         //定义一个学校对象
    20         School sc = new School("China", teachers);
    21         
    22         //创建一个OgnlContext对象
    23         OgnlContext context  = new OgnlContext();
    24         
    25         //将老师和学校放入上下文环境中
    26         context.put("t1", t1);
    27         context.put("sc", sc);
    28         
    29         //未设置根对象之前,根对象为null
    30         System.out.println("根对象:"+context.getRoot());
    31         
    32         //设置学校为根对象
    33         context.setRoot(sc);
    34         System.out.println("设置根对象:"+context.getRoot());
    35         //若继续设置根对象,会覆盖前面的根对象
    36         //context.setRoot(t1);
    37         
    38         //获取根对象属性
    39         //获取根对象的属性值,可以直接使用属性名作为表达式,也可以使用#对象名.属性名的方式;
    40         Object expression = Ognl.parseExpression("name");
    41         //Object expression = Ognl.parseExpression("#sc.name");
    42         
    43         Object result = Ognl.getValue(expression, context, context.getRoot());
    44         // 获取根对象的信息,使用#获取上下文中的属性值时,必须使用带Map context参数getValue方法,指定上下文环境
    45         // 获取根对象的信息,直接获取,没有使用#,则可以使用不带Map context参数getValue方法
    46         Object result1 = Ognl.getValue(expression, context.getRoot());
    47         System.out.println("获取根对象的属性值:"+result);
    48         System.out.println("获取根对象的属性值:"+result1);
    49         
    50         //获取普通对象的属性值,则必须使用#对象名.属性名的方式获取
    51         expression = Ognl.parseExpression("#t1.name");
    52         result = Ognl.getValue(expression, context, context.getRoot());
    53         System.out.println("获取普通对象的属性值:"+result);
    54         
    55         //调用根对象中的方法
    56         expression = Ognl.parseExpression("getName()");
    57         expression = Ognl.parseExpression("#sc.getName()");
    58         result = Ognl.getValue(expression, context, context.getRoot());
    59         System.out.println("调用根对象中的方法:"+result);
    60         
    61         //调用普通对象中的方法
    62         expression  = Ognl.parseExpression("#t1.getAge()");
    63         result = Ognl.getValue(expression, context, context.getRoot());
    64         System.out.println("调用普通对象中的方法:"+result);
    65         expression  = Ognl.parseExpression("#t1.getName().length()");
    66         result = Ognl.getValue(expression, context, context.getRoot());
    67         System.out.println("调用普通对象中的方法:"+result);
    68         
    69         //调用根对象中的静态方法
    70         expression = Ognl.parseExpression("test00()");
    71         expression = Ognl.parseExpression("#sc.test00()");
    72         result = Ognl.getValue(expression, context, context.getRoot());
    73         System.out.println("调用根对象中的静态方法:"+result);
    74         
    75         //调用API中的静态方法
    76         expression = Ognl.parseExpression("@java.lang.Math@floor(4.5)");
    77         result = Ognl.getValue(expression, context, context.getRoot());
    78         System.out.println("调用API中的静态方法:"+result);
    79         
    80         //调用API中的静态属性
    81         expression = Ognl.parseExpression("@java.lang.Math@PI");
    82         result = Ognl.getValue(expression, context, context.getRoot());
    83         System.out.println("调用API中的静态属性:"+result);
    84         
    85     }
    86 
    87 }

    在school.java中新加了一个静态函数:

    1     public static String test00(){
    2         
    3         return "thank you";        
    4     }

    运行上面的测试code:

    根对象:null
    设置根对象:OGNL.School@11028347
    获取根对象的属性值:China
    获取根对象的属性值:China
    获取普通对象的属性值:zhangsan
    调用根对象中的方法:China
    调用普通对象中的方法:30
    调用普通对象中的方法:8
    调用根对象中的静态方法:thank you
    调用API中的静态方法:4.0
    调用API中的静态属性:3.141592653589793.

    所以到此我们可以看到OGNL实际上就是提供另一种方式来调用对象的任意属性和方法。

    4.Ognl获取数组、集合、Map中元素的方法

    Ognl表达式可以创建实例对象,以及获取实例对象中的属性,下面我们看看怎么通过Ognl创建一个集合、map以及通过Ognl获取里面的元素。

     1 package OGNL;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Collections;
     5 import java.util.HashMap;
     6 import java.util.List;
     7 import java.util.Map;
     8 
     9 import ognl.Ognl;
    10 import ognl.OgnlContext;
    11 import ognl.OgnlException;
    12 
    13 public class Test02 {
    14 
    15     public static void main(String[] args) throws OgnlException {
    16         
    17         OgnlContext context = new OgnlContext();
    18         
    19         // 通过Ognl可以创建java的实例对象,只有是类的完整路径
    20         Object expression = Ognl.parseExpression("new java.util.ArrayList()");
    21         Object result = Ognl.getValue(expression, context, context.getRoot());
    22         System.out.println("Ognl创建实例:"+result);
    23         
    24         //注意这种自定义的类,一定要填写类的完整路径
    25         expression = Ognl.parseExpression("new OGNL.Teacher('zhangsan','男',30)");
    26         result = Ognl.getValue(expression, context, context.getRoot());
    27         System.out.println("Ognl创建实例:"+result);
    28         
    29         // 通过Ognl可以创建一个初始化的List 
    30         expression = Ognl.parseExpression("{'a', 'b', 'c', 'd'}"); 
    31         //expression = Ognl.parseExpression("['a', 'b', 'c', 'd']"); //这个报错
    32         result = Ognl.getValue(expression, context, context.getRoot()); 
    33         System.out.println("Ognl初始化List:"+result);
    34         
    35         // 通过Ognl可以创建一个初始化的Map,注意此时得加上#符号
    36         expression = Ognl.parseExpression("#{'a':'aa', 'b':'bb', 'c':'cc', 'd':'dd'}");
    37         // 创建指定类型的Map
    38         // expression = Ognl.parseExpression("#@java.util.TreeMap@{'a':'aa', 'b':'bb', 'c':'cc', 'd':'dd'}");
    39         result = Ognl.getValue(expression, context, context.getRoot());
    40         System.out.println("Ognl初始化Map:"+result);
    41         
    42         // 通过Ognl访问数组中的元素 
    43         String[] name1 = {"liu", "xu"}; 
    44         context.put("name1", name1); 
    45         // 直接通过数组名+下标 
    46         expression = Ognl.parseExpression("#name1[1]"); 
    47         result = Ognl.getValue(expression, context, context.getRoot()); 
    48         System.out.println("通过Ognl访问数组中的元素:"+result);
    49         
    50         // 通过Ognl访问集合中的元素 
    51         List<String> name2 = new ArrayList<String>(); 
    52         Collections.addAll(name2, name1); //将name1中的数据copy到name2中。
    53         context.put("name2", name2); 
    54         // 直接通过集合名+下标
    55         expression = Ognl.parseExpression("#name2[0]"); 
    56         result = Ognl.getValue(expression, context, context.getRoot()); 
    57         System.out.println("通过Ognl访问集合中的元素:"+result);
    58         
    59         // 通过Ognl访问Map中的元素         
    60         Map<Integer, String> name3 = new HashMap<Integer, String>(); 
    61         name3.put(1, "liu"); 
    62         name3.put(2, "xu"); 
    63         context.put("name3", name3); 
    64         // 直接通过map名+key 
    65         expression = Ognl.parseExpression("#name3[1]"); 
    66         result = Ognl.getValue(expression, context, context.getRoot()); 
    67         System.out.println("通过Ognl访问Map中的元素 :"+result);    
    68 
    69     }
    70 
    71 }

    运行结果:

    Ognl创建实例:[]
    Ognl创建实例:OGNL.Teacher@2aaf7cc2
    Ognl初始化List:[a, b, c, d]
    Ognl初始化Map:{a=aa, b=bb, c=cc, d=dd}
    通过Ognl访问数组中的元素:xu
    通过Ognl访问集合中的元素:liu
    通过Ognl访问Map中的元素 :liu

    注意点
    1.创建集合不用加#,创建map要加#
    2.创建类的一个对象,要使用类的完整路径
    3.要创建带有初始化值的指定类型的List或Map,可以这样#@java.util.TreeMap@{‘key’:’value’,’key’:’value’,……}

    OGNL还有其他用法。这里不再细说。通过上面的例子,我们可以看出,OGNL大概作用是什么:就是用来获取对象的属性和方法。

    记住OGNL的表达式、根对象、上下文OgnlContext.

    上面的例子中我们可以看到,都是直接调用了OgnlContext这个类,创建了context,我们用OGNL的时候,第二个参数就是context, 第三个参数就是context,getRoot()。

    实际上这个上下文环境我们是可以自定义的,根对象我们也是可以自定义的。我们来看看下面的例子:

      1 package OGNL;
      2 
      3 public class Address {
      4     
      5     private String city;
      6     private String Street;
      7     /**
      8      * @return the city
      9      */
     10     public String getCity() {
     11         return city;
     12     }
     13     /**
     14      * @param city the city to set
     15      */
     16     public void setCity(String city) {
     17         this.city = city;
     18     }
     19     /**
     20      * @return the street
     21      */
     22     public String getStreet() {
     23         return Street;
     24     }
     25     /**
     26      * @param street the street to set
     27      */
     28     public void setStreet(String street) {
     29         Street = street;
     30     }
     31 }
     32 
     33 
     34 package OGNL;
     35 
     36 public class User {
     37     
     38     private String name;
     39     private int age;
     40     private String password;
     41     private Address address;
     42     /**
     43      * @return the name
     44      */
     45     public String getName() {
     46         return name;
     47     }
     48     /**
     49      * @param name the name to set
     50      */
     51     public void setName(String name) {
     52         this.name = name;
     53     }
     54     /**
     55      * @return the age
     56      */
     57     public int getAge() {
     58         return age;
     59     }
     60     /**
     61      * @param age the age to set
     62      */
     63     public void setAge(int age) {
     64         this.age = age;
     65     }
     66     /**
     67      * @return the password
     68      */
     69     public String getPassword() {
     70         return password;
     71     }
     72     /**
     73      * @param password the password to set
     74      */
     75     public void setPassword(String password) {
     76         this.password = password;
     77     }
     78     /**
     79      * @return the address
     80      */
     81     public Address getAddress() {
     82         return address;
     83     }
     84     /**
     85      * @param address the address to set
     86      */
     87     public void setAddress(Address address) {
     88         this.address = address;
     89     }
     90 }
     91 
     92 package OGNL;
     93 
     94 import java.util.HashMap;
     95 
     96 import ognl.Ognl;
     97 import ognl.OgnlException;
     98 
     99 public class Test03 {
    100 
    101     public static void main(String[] args) throws OgnlException {
    102         
    103         User user = new User();
    104         user.setName("zhangsan");
    105         
    106         //将user对象作为OGNL的根,编写OGNL表达式来获取user对象中的各种属性值
    107         //直接编写属性名,即获取user对象中的属性值
    108         String name = (String) Ognl.getValue("name", new HashMap(), user);
    109         System.out.println("0000:"+name);
    110         
    111         //获取javaBean中另一个对象的属性值,用xxx.yyy
    112         Address ads = new Address();
    113         ads.setCity("baoding");
    114         user.setAddress(ads);
    115         String result = (String) Ognl.getValue("address.city", new HashMap(), user);
    116         System.out.println("1111:"+result);
    117         
    118         //对JavaBean中的属性进行赋值操作
    119         Ognl.getValue("name='zhaosi'", new HashMap(), user);
    120         System.out.println("2222:"+user.getName());
    121         Ognl.getValue("setName('wangwu')", new HashMap(), user);
    122         System.out.println("3333:"+user.getName());
    123         //上面是两种赋值方式:
    124         /*1:属性=value
    125             Ognl.getValue("name='zhaosi'", new HashMap(), user);        
    126         2:setName(value)
    127             Ognl.getValue("setName('wangwu')", new HashMap(), user);
    128         */
    129     }
    130 
    131 }

    运行结果:

    0000:zhangsan
    1111:baoding
    2222:zhaosi
    3333:wangwu

    可以看到这个例子中直接将user作为对象去使用。并且上下文环境直接是新建了一个HashMap。

    上面两个例子都是讲解OGNL基本用法,主要区别就在于第二个例子中,都是将对象直接作为根对象去使用。没有用到OgnlContext这个类。

     https://www.cnblogs.com/whgk/p/6600393.html

    https://blog.csdn.net/a_helloword/article/details/80432364-----参考博客

    作者:全网第一菜
    来源:CSDN
    原文:https://blog.csdn.net/a_helloword/article/details/80432364

  • 相关阅读:
    Python算法与数据结构--求所有子数组的和的最大值
    Python算法练习--把搜索树转成双向链表
    将HTML字符转换为DOM节点并动态添加到文档中
    设计包含min函数的栈
    Python学习:类和实例
    Javascript 装饰器极速指南
    【翻译】旧技术成就新勒索软件,Petya添加蠕虫特性
    textarea的中文输入判断与搜狗输入法的特殊行为
    python 人工智能资源推荐
    Python 黑客相关电子资源和书籍推荐
  • 原文地址:https://www.cnblogs.com/beilou310/p/10636184.html
Copyright © 2020-2023  润新知