iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Struts2中OGNL表达式的原理是什么
  • 682
分享到

Struts2中OGNL表达式的原理是什么

2023-06-17 10:06:41 682人浏览 八月长安
摘要

Struts2中OGNL表达式的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、OGNL表达式基础知识 二、OGNL与Struts2OGNL表达式OGNL

Struts2中OGNL表达式的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

一、OGNL表达式基础知识 

二、OGNL与Struts2

OGNL表达式

OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,它旨在提供一个更高的更抽象的层次来对Java对象图进行导航。

OGNL表达式的基本单位是"导航链",一般导航链由如下几个部分组成:

  1. 属性名称(property) 

  2. 方法调用(method invoke) 

  3. 数组元素

所有的OGNL表达式都基于当前对象的上下文来完成求值运算,链的前面部分的结果将作为后面求值的上下文。例如:names[0].length()。

示例:第一个OGNL程序

public class OGNL1  {      public static void main(String[] args)      {                   Person person = new Person();          person.setName("zhangsan");                    try         {                           Object value = Ognl.getValue("name", person);               System.out.println(value);          }          catch (OgnlException e)          {              e.printStackTrace();          }      }  }   class Person  {      private String name;       public String getName()      {          return name;      }       public void setName(String name)      {          this.name = name;      }  }

控制台输出:

zhangsan

可以看到我们正确的取得了person对象的name属性值,该getValue声明如下:

public static <T> T getValue(String expression,Object root)throws OgnlException   Convenience method that combines calls to  parseExpression  and  getValue.    Parameters:  expression - the OGNL expression to be parsed  root - the root object for the OGNL expression   Returns:  the result of evaluating the expression

OGNL会根据表达式从根对象(root)中提取值。

示例:上下文环境中使用OGNL

public class OGNL1  {      public static void main(String[] args)      {                   Map<String , Object> context = new HashMap<String , Object>();           Person person1 = new Person();          person1.setName("zhangsan");                    Person person2 = new Person();          person2.setName("lisi");           Person person3 = new Person();          person3.setName("wangwu");                    Person person4 = new Person();          person4.setName("zhaoliu");                    context.put("person1", person1);          context.put("person2", person2);          context.put("person3", person3);           try         {                           Object value = Ognl.getValue("name", context, person2);              System.out.println("ognl expression \"name\" evaluation is : " + value);                            Object value2 = Ognl.getValue("#person2.name", context, person2);              System.out.println("ognl expression \"#person2.name\" evaluation is : " + value2);                            Object value3 = Ognl.getValue("#person1.name", context, person2);              System.out.println("ognl expression \"#person1.name\" evaluation is : " + value3);                            Object value4 = Ognl.getValue("name", context, person4);              System.out.println("ognl expression \"name\" evaluation is : " + value4);                            Object value5 = Ognl.getValue("#person4.name", context, person4);              System.out.println("ognl expression \"person4.name\" evaluation is : " + value5);                            // Object value6 = Ognl.getValue("#person4.name", context, person2);              // System.out.println("ognl expression \"#person4.name\" evaluation is : " + value6);           }          catch (OgnlException e)          {              e.printStackTrace();          }      }  }   class Person  {      private String name;       public String getName()      {          return name;      }       public void setName(String name)      {          this.name = name;      }  }

控制台输出:

ognl expression "name" evaluation is : lisi  ognl expression "#person2.name" evaluation is : lisi  ognl expression "#person1.name" evaluation is : zhangsan  ognl expression "name" evaluation is : zhaoliu  ognl.OgnlException: source is null for getProperty(null, "name")      at ognl.OgnlRuntime.getProperty(OgnlRuntime.java:2296)      at ognl.ASTProperty.getValueBody(ASTProperty.java:114)      at ognl.Simplenode.evaluateGetValueBody(SimpleNode.java:212)      at ognl.SimpleNode.getValue(SimpleNode.java:258)      at ognl.ASTChain.getValueBody(ASTChain.java:141)      at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)      at ognl.SimpleNode.getValue(SimpleNode.java:258)      at ognl.Ognl.getValue(Ognl.java:494)      at ognl.Ognl.getValue(Ognl.java:596)      at ognl.Ognl.getValue(Ognl.java:566)      at com.beliefbetrayal.ognl.OGNL1.main(OGNL1.java:53)

对于使用上下文的OGNL,若不指定从哪一个对象中查找"name"属性,则OGNL直接从根对象(root)查找,若指定查找对象(使用'#'号指定,如#person1),则从指定的对象中查找,若指定对象不在上下文中则会抛出异常,换句话说就是是#person1.name形式指定查找对象则必须要保证指定对象在上下文环境中。

示例:使用OGNL调用方法

public class OGNL2  {      public static void main(String[] args)      {                   OgnlContext context = new OgnlContext();           People people1 = new People();          people1.setName("zhangsan");           People people2 = new People();          people2.setName("lisi");           People people3 = new People();          people3.setName("wangwu");           context.put("people1", people1);          context.put("people2", people2);          context.put("people3", people3);                    context.setRoot(people1);           try         {                           Object value = Ognl.getValue("name.length()", context, context.getRoot());              System.out.println("people1 name length is :" + value);                            Object upperCase = Ognl.getValue("#people2.name.toUpperCase()", context, context.getRoot());              System.out.println("people2 name upperCase is :" + upperCase);               Object invokeWithArgs = Ognl.getValue("name.charAt(5)", context, context.getRoot());              System.out.println("people1 name.charAt(5) is :" + invokeWithArgs);                            Object min = Ognl.getValue("@java.lang.Math@min(4,10)", context, context.getRoot());              System.out.println("min(4,10) is :" + min);                            Object e = Ognl.getValue("@java.lang.Math@E", context, context.getRoot());              System.out.println("E is :" + e);          }          catch (OgnlException e)          {              e.printStackTrace();          }      }  }   class People  {      private String name;       public String getName()      {          return name;      }       public void setName(String name)      {          this.name = name;      }  }

控制台输出:

people1 name length is :8 people2 name upperCase is :LISI  people1 name.charAt(5) is :s  min(4,10) is :4 E is :2.718281828459045

使用OGNL调用方法也十分简单,对于成员方法调用,只需要给出方法的名称+(),若有参数,直接写在括号内,与一般调用Java方法一致。对于静态方法的调用,需要使用如下格式:@ClassName@method,对于静态变量需要使用如下格式:@ClassName@field。

示例:使用OGNL操作集合

public class OGNL3  {      public static void main(String[] args) throws Exception      {          OgnlContext context = new OgnlContext();                    Classroom classroom = new Classroom();          classroom.getStudents().add("zhangsan");          classroom.getStudents().add("lisi");          classroom.getStudents().add("wangwu");          classroom.getStudents().add("zhaoliu");          classroom.getStudents().add("qianqi");                    Student student = new Student();          student.getContactWays().put("homeNumber", "110");          student.getContactWays().put("companyNumber", "119");          student.getContactWays().put("mobilePhone", "112");                    context.put("classroom", classroom);          context.put("student", student);          context.setRoot(classroom);                    Object collection = Ognl.getValue("students", context, context.getRoot());          System.out.println("students collection is :" + collection);                    Object firstStudent = Ognl.getValue("students[0]", context, context.getRoot());          System.out.println("first student is : " + firstStudent);                    Object size = Ognl.getValue("students.size()", context, context.getRoot());          System.out.println("students collection size is :" + size);           System.out.println("--------------------------飘逸的分割线--------------------------");                    Object mapCollection = Ognl.getValue("#student.contactWays", context, context.getRoot());          System.out.println("mapCollection is :" + mapCollection);           Object firstElement = Ognl.getValue("#student.contactWays['homeNumber']", context, context.getRoot());          System.out.println("the first element of contactWays is :" + firstElement);           System.out.println("--------------------------飘逸的分割线--------------------------");                    Object createCollection = Ognl.getValue("{'aa','bb','cc','dd'}", context, context.getRoot());          System.out.println(createCollection);                    Object createMapCollection = Ognl.getValue("#{'key1':'value1','key2':'value2'}", context, context.getRoot());          System.out.println(createMapCollection);       }  }   class Classroom  {      private List<String> students = new ArrayList<String>();       public List<String> getStudents()      {          return students;      }       public void setStudents(List<String> students)      {          this.students = students;      }  }   class Student  {      private Map<String , Object> contactWays = new HashMap<String , Object>();       public Map<String , Object> getContactWays()      {          return contactWays;      }       public void setContactWays(Map<String , Object> contactWays)      {          this.contactWays = contactWays;      }  }

控制台的输出:

students collection is :[zhangsan, lisi, wangwu, zhaoliu, qianqi]  first student is : zhangsan  students collection size is :5 --------------------------飘逸的分割线--------------------------  mapCollection is :{homeNumber=110, mobilePhone=112, companyNumber=119}  the first element of contactWays is :110 --------------------------飘逸的分割线--------------------------  [aa, bb, cc, dd]  {key1=value1, key2=value2}

OGNL不仅可以操作集合对象,还可以创建集合对象,对集合操作与对属性的操作没什么不同,需要注意的是OGNL认为List与Array是一样的。使用OGNL创建List集合时使用{},创建Map对象时使用#{}。

示例:使用OGNL过滤集合与投影集合

public class OGNL4  {      public static void main(String[] args) throws Exception      {          OgnlContext context = new OgnlContext();           Humen humen = new Humen();          humen.setName("qiuyi");          humen.setSex("n");          humen.setAge(22);          humen.getFriends().add(new Humen("zhangsan" , "n" , 22));          humen.getFriends().add(new Humen("lisi" , "f" , 21));          humen.getFriends().add(new Humen("wangwu" , "n" , 23));          humen.getFriends().add(new Humen("zhaoliu" , "n" , 22));          humen.getFriends().add(new Humen("qianqi" , "n" , 22));          humen.getFriends().add(new Humen("sunba" , "f" , 20));          humen.getFriends().add(new Humen("yangqiu" , "f" , 25));                    context.put("humen", humen);          context.setRoot(humen);                    Object filterCollection = Ognl.getValue("friends.{? #this.name.length() > 7}", context, context.getRoot());          System.out.println("filterCollection is :" + filterCollection);           System.out.println("--------------------------飘逸的分割线--------------------------");                    Object projectionCollection = Ognl.getValue("friends.{name}", context, context.getRoot());          System.out.println("projectionCollection is :" + projectionCollection);      }  }   class Humen  {      private String name;      private String sex;      private int age;      private List<Humen> friends = new ArrayList<Humen>();       public Humen()      {       }       public Humen(String name , String sex , int age)      {          this.name = name;          this.sex = sex;          this.age = age;      }       public String getName()      {          return name;      }       public void setName(String name)      {          this.name = name;      }       public String getSex()      {          return sex;      }       public void setSex(String sex)      {          this.sex = sex;      }       public int getAge()      {          return age;      }       public void setAge(int age)      {          this.age = age;      }       public List<Humen> getFriends()      {          return friends;      }       public void setFriends(List<Humen> friends)      {          this.friends = friends;      }       @Override     public String toString()      {          return "Humen [name=" + name + ", sex=" + sex + ", age=" + age + "]";      }  }

控制台输出:

filterCollection is :[Humen [name=zhangsan, sex=n, age=22]]  --------------------------飘逸的分割线--------------------------  projectionCollection is :[zhangsan, lisi, wangwu, zhaoliu, qianqi, sunba, yangqiu]

OGNL可以对集合进行过滤与投影操作,过滤的语法为collection.{? expression},其中使用"#this"表示集合当前对象(可以与for-each循环比较)。投影的语法为collection.{expression}。投影和过滤可以看做是数据库中对表取列和取行的操作。


Struts2与OGNL

Struts 2支持以下几种表达式语言:
1. OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;
2. jsTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;
3. Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如python、Ruby和Smarttalk等)的一些起特性;
4. Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。

Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
1. 支持对象方法调用,如xxx.doSomeSpecial();
2. 支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@fORMat('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
3. 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;
4. 访问OGNL上下文(OGNL context)和ActionContext;
5. 操作集合对象。

&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;&mdash;以上内容引用自Http://www.blogjava.net/max/arcHive/2007/04/28/114417.html

平时使用Struts2标签时会出现一些很奇特的问题,对于OGNL不了解的人可能对问题的出现无能为力或者就算解决了问题也不知道是如何解决的。下面总结一些使用Struts2标签容易出现的困惑:

问题一:#,%{},$符号

在Struts2标签属性中经常会出现"#"或者"%{}"的符号出现,通过上面OGNL表达式基础的介绍,知道了OGNL上下文中有且仅有一个根对象。Struts2为我们定义了许多明明对象,他们分别是"ValueStack","Parameters","Session","Request", "Appliction","Attr",其中"ValueStack"被设置为上下文的根对象。访问非根对象必须加上"#"号,这就是出现"#"的原因。Struts2中的标的处理类,并不是所有都将标签的属性作为OGNL表达式来看待,有时候我们需要设置动态地值,则必须告诉标签的处理类该字符串按照OGNL表达式来处理,%{}符号的作用就是告诉标签的处理类将它包含的字符串按照OGNL表达式处理。 "$"符号用于XML文件中用于获取动态值,与%{}作用类似。

问题二:%{}符号的影响

Struts2的标签几十几百个,要记住哪一个标签的处理类将标签的属性作为OGNL表达式是一件很困难的事情,在不清楚处理类的处理方式时怎么办,%{}对于标签处理类来说,若处理类将属性值作为普通字符串则%{}符号包含的字符串当做OGNL表达式,若处理类将属性值作为OGNL表达式来处理,则直接忽略%{}符号。换句话说,不清楚处理方式的话,可以都使用%{}符号。

问题三:标签是如何获得数据

下面是ValueStack的官方描述:

ValueStack allows multiple beans to be pushed in and dynamic EL expressions to be evaluated against it. When evaluating an expression, the stack will be searched down the stack, from the latest objects pushed in to the earliest, looking for a bean with a getter or setter for the given property or a method of the given name (depending on the expression being evaluated).

大致意思:ValueStack允许保存多个bean(也就是Action),并且可以使用表达式语言获得他们。当评估一个表达式,ValueStack将会从栈顶到栈底的方向被搜索一遍,对于给定的属性名称寻找bean的getter或setter方法或寻找给定的方法。

Struts2中OGNL表达式的原理是什么

每当一个请求到达Action时,Struts2会将Action对象推入ValueStack中。

<body>       username:<s:property value="username"/><br />      -------------------诡异的分割线-------------------<br />      username:<%= ((HelloWorldAction)ActionContext.getContext().getValueStack().peek()).getUsername() %><br />    </body>

页面显示结果:

username:zhangsan  -------------------诡异的分割线-------------------  username:zhangsan

可以看到标签取值与用Java代码取值的结果相同,明显标签的取值方式更简练简洁。OGNL表达式"username"表示了从根对象ValueStack中取出属性username的值。它会从栈顶到栈底遍历ValueStack,直到找某一个Action中的"username"属性。

看完上述内容,你们掌握Struts2中OGNL表达式的原理是什么的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网精选频道,感谢各位的阅读!

--结束END--

本文标题: Struts2中OGNL表达式的原理是什么

本文链接: https://www.lsjlt.com/news/288496.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Struts2中OGNL表达式的原理是什么
    Struts2中OGNL表达式的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、OGNL表达式基础知识 二、OGNL与Struts2OGNL表达式OGNL...
    99+
    2023-06-17
  • 怎么在Struts2中利用OGNL表达式对map进行遍历
    这篇文章给大家介绍怎么在Struts2中利用OGNL表达式对map进行遍历,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一.Action中的代码:MapAction.javapackage com.zx.demo.ac...
    99+
    2023-05-31
    struts2 遍历 ognl表达式
  • struts2 el表达式的作用是什么
    Struts2 EL表达式的作用是在JSP页面中访问和操作Struts2框架中的数据和对象。EL表达式可以简化JSP页面的编写,提高...
    99+
    2023-10-27
    struts2
  • Mybatis中的常用OGNL表达式
    目录Mybatis常用的OGNL表达式如下Mybatis jstl表达式在Mybatis的动态SQL和${}形式的参数中都用到了OGNL表达式。 Mybatis常用的OGNL表达式如...
    99+
    2024-04-02
  • Java Lambda表达式的原理是什么
    这篇文章主要介绍“Java Lambda表达式的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java Lambda表达式的原理是什么”文章能帮助大家解决问题。1、实例...
    99+
    2023-07-05
  • Mybatis中的常用OGNL表达式有哪些
    本文小编为大家详细介绍“Mybatis中的常用OGNL表达式有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“Mybatis中的常用OGNL表达式有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Mybat...
    99+
    2023-07-02
  • Mybatis中的动态sql怎么利用OGNL表达式进行处理
    Mybatis中的动态sql怎么利用OGNL表达式进行处理?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。常用的Mybatis动态sql标签有6种:  &nb...
    99+
    2023-05-31
    mybatis ognl表达式 动态sql
  • Python正则表达式的基本原理是什么
    这篇文章主要讲解了“Python正则表达式的基本原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python正则表达式的基本原理是什么”吧!正则表达式是什么?正则表达式,又称规则表达...
    99+
    2023-07-06
  • PHP中正则表达式中的原子是什么
    这篇文章给大家介绍PHP中正则表达式中的原子是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。正则表达式中的原子什么是原子:组成正则表达式的最小单位就是原子。原子有哪些内容组成:正常的字母都是原子,所有可见字符都是原...
    99+
    2023-06-15
  • JavaScript中的表达式是什么
    今天给大家介绍一下JavaScript中的表达式是什么。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。在JavaScript中...
    99+
    2024-04-02
  • python中什么是表达式
    今天就跟大家聊聊有关python中什么是表达式,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。说明Python表达式是变量、常量、计算符和方法调用的序列,它执行指定的计算,并返回某个确...
    99+
    2023-06-20
  • Java中的Lambda表达式是什么
    这篇文章主要介绍“Java中的Lambda表达式是什么”,在日常操作中,相信很多人在Java中的Lambda表达式是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中的Lambda表达式是什么”的疑...
    99+
    2023-06-25
  • 正则表达式原理及常用示例是什么
    这期内容当中小编将会给大家带来有关正则表达式原理及常用示例是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、正则的含义正则表达式就是用来操作字符串的一种逻辑公式二、正则表达式的应用场景数据分析时数据...
    99+
    2023-06-26
  • java中Lamda表达式是什么
    java中Lamda表达式是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Lamda表达式λ 希腊字母表中排序第十一位的字母,英语名称为 Lamda避免匿名内部类定义过多可...
    99+
    2023-06-22
  • struts2拦截器的工作原理是什么
    Struts2拦截器的工作原理是基于责任链模式。当请求到达Struts2框架时,它会依次经过一系列的拦截器。每个拦截器可以在请求被传...
    99+
    2023-10-24
    struts2
  • Struts2拦截器的实现原理是什么
    Struts2拦截器的实现原理是什么?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Struts2的核心在于它复杂的拦截器,几乎70%的工作都是由拦截器完成的。比...
    99+
    2023-05-31
    struts st
  • 什么是VBS中的正则表达式
    本篇内容主要讲解“什么是VBS中的正则表达式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“什么是VBS中的正则表达式”吧!早期起源正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研...
    99+
    2023-06-09
  • LINQ表达式是什么
    这篇文章主要讲解了“LINQ表达式是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“LINQ表达式是什么”吧!LINQ表达式简介OO(面向对象)以外的疆域:信息的访问与整合。关系数据库与X...
    99+
    2023-06-17
  • Access中表达式的用法是什么
    Access中的表达式用于计算和组合数据,以创建新的数据或控制数据的呈现方式。表达式可以在查询、表单、报告和宏中使用。以下是一些常见...
    99+
    2023-09-28
    access
  • 什么是css表达式
    什么是css表达式,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 css表达式就是在css属性后使用expre...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作