【Struts2】8.OGNL

来源:互联网 发布:地税 优化行政审批 编辑:程序博客网 时间:2024/05/29 14:07

一、OGNL表达式学习

1.OGNL表达式语言

访问上下文(Context)中的对象需要使用#符号标注命名空间,如#appaication、#session
OGNL会设定一个根对象(root对象),在Struts2中根对象就是ValueStack(值栈)。若要访问根对象中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。

在Struts2中,根对象ValueStack的实现类为OgnlValueStack,该对象不是我们想象的只存放单个值,而是存放一组对象。在OgnlValueStack类中有一个List类型的root变量,就是使用它来存放一组对象。
                    |--request
                    |--application
context------|--OgnlValueStack  root变量[action,OgnlUtil,....]
                    |--session
                    |--attr
                    |--parameters
  在root变量中处于第一位的对象叫栈顶对象,通常在OGNL表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,若栈顶对象不存在该属性,就会从第二个对象寻找,若没有找到就从第三个对象寻找,依次往下访问,知道找到为止。
需注意:在Struts2中,OGNL表达式需要配合Struts标签才可使用。<s:property value="name"/>   

由于ValueStack是Struts2中OGNL的根对象,若用户需要访问值栈中的对象,在JSP页面可以直接通过下面的EL表达式访问值栈中对象的属性:${foo} //获得值栈中某个对象的foo属性
若访问其他Context中的对象,由于他们不是根对象,所以在访问时,需要添加#前缀。
application对象:用来访问ServletContext,例如#application.username或者#application['username'],相当于调用ServletContext的getAttribute("username");
session对象:用来访问HttpSession,例如#session.username或者#session['username'],相当于调用session.getAttribute("username");
request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.username或者#request['username'],相当于调用request.getAttribute("username");
parameters对象:用来访问HTTP的请求参数,例如#parameters.username或者#parameters['username'],相当于调用request.getParameter("username");
attr对象:用于按page→request→session→application顺序访问其属性。

为何使用EL表达式能够访问值栈中对象的属性?
原因是Struts2对HttpServletRequest作了进一步的封装。
public class StrutsRequestWrapper extends HttpServletRequestWrapper {public StrutsRequestWrapper(HttpServletRequest request) {super(request);}public Object getAttribute(String s){...ActionContext ctx = ActionContext.getContext();Object attribute = super.getAttribute(s);//先从request范围获取属性值if(ctx!=null){if(attribute == null){//如果从request范围没有找到属性值,就从值栈中查找对象的属性值....ValueStack vs = ctx.getValueStack();attribute = vs.findValue(s);...}}return attribute;}}

二、OGNL表达式学习



























三、OGNL表达式学习

ognl所需jar包为ognl-3.0.jar和javassist-3.7.jar

1.OgnlContext 上下文对象,实现了Map接口,是一个map对象。存在唯一的叫做根的对象(root),可以通过程序设定上下文中的那个对象作为根对象。
2.在OGNL中,如果表达式没有使用#号,那么OGNL会从根对象中寻找该属性对应的get方法,如果寻找的不是根对象中的属性,则需要以#号开头,找到对应对象的属性。
3.当使用OGNL调用静态方法或者静态属性时,需要按照如下方法编写表达式@package.calssname@methodname(parameter)或者@package.calssname@attributename,其中Math类的调用比较特殊,只需要@@methodname(parameter)
4.数组和集合是一样的,都是通过下标来访问。
5.使用OGNL处理映射(Map)的语法格式为:#{'key1':'value1''key2':'value2'...};
6.过滤(filtering  类比数据库中的表,针对行记录):collection.{? expression},符合表达式expression的集合collection,获取集合中符合条件的第一个元素的方式也可以是collection.{^ expression},获取集合中符合条件的最后一个元素的方式也可以是collection.{$ expression}.
7.在使用过滤操作时,我们通常会使用#this,该表达式用于代表当前正在迭代的集合中的对象。
8.OGNL针对集合提供了一些伪属性(如size,isEmpty),让我们可以通过属性的方式来调用方法,也可以通过调用方法来实现相同的目的。
9.投影(projection  类比数据库中的表,针对列记录):collection.{expression},对集合进行表达式expression的操作后的集合,获取集合中符合条件的第一个元素的方式也可以是collection.{^ expression},获取集合中符合条件的最后一个元素的方式也可以是collection.{$ expression}.
示例:
Person类
public class Person {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}
Dog类
public class Dog {private String name;private String[] friends;public String getName() {return name;}public void setName(String name) {this.name = name;}public String[] getFriends() {return friends;}public void setFriends(String[] friends) {this.friends = friends;}}
测试类
import java.util.ArrayList;import java.util.List;import ognl.Ognl;import ognl.OgnlContext;public class OgnlTest {public static void main(String[] args) throws Exception {Person p = new Person();p.setName("zhangsan");Dog d = new Dog();d.setName("wangcai");d.setFriends(new String[]{"aa","bb","cc","dd"});OgnlContext context = new OgnlContext();context.put("p", p);context.put("d", d);context.setRoot(p);//ognl 解析表达式Object obj1 = Ognl.parseExpression("name");System.out.println(obj1);Object obj2 = Ognl.getValue(obj1, context, context.getRoot());System.out.println(obj2);System.out.println("================");Object obj3 = Ognl.parseExpression("#p.name");System.out.println(obj3);Object obj4 = Ognl.getValue(obj3, context, context.getRoot());System.out.println(obj4);System.out.println("================");Object obj5 = Ognl.parseExpression("#d.name");System.out.println(obj5);Object obj6 = Ognl.getValue(obj5, context, context.getRoot());System.out.println(obj6);System.out.println("================");//调用方法Object obj7 = Ognl.parseExpression("name.toUpperCase()");System.out.println(obj7);Object obj8 = Ognl.getValue(obj7, context, context.getRoot());System.out.println(obj8);System.out.println("================");//调用某个类的静态方法并传递参数Object obj9 = Ognl.parseExpression("@java.lang.Integer@toBinaryString(10)");System.out.println(obj9);Object obj10 = Ognl.getValue(obj9, context, context.getRoot());System.out.println(obj10);System.out.println("================");//特殊类调用的静态方法并传递参数Object obj11 = Ognl.parseExpression("@@min(4,10)");System.out.println(obj11);Object obj12 = Ognl.getValue(obj11, context, context.getRoot());System.out.println(obj12);System.out.println("================");//创建对象Object obj13 = Ognl.parseExpression("new java.util.LinkedList()");System.out.println(obj13);Object obj14 = Ognl.getValue(obj13, context, context.getRoot());System.out.println(obj14);System.out.println("================");Object obj15 = Ognl.parseExpression("{'aa','bb','cc'}");System.out.println(obj15);Object obj16 = Ognl.getValue(obj15, context, context.getRoot());System.out.println(obj16);System.out.println("================");Object obj17 = Ognl.parseExpression("{'aa','bb','cc'}[2]");System.out.println(obj17);Object obj18 = Ognl.getValue(obj17, context, context.getRoot());System.out.println(obj18);System.out.println("================");//访问数组Object obj19 = Ognl.parseExpression("#d.friends");System.out.println(obj19);Object obj20 = Ognl.getValue(obj19, context, context.getRoot());System.out.println(obj20);System.out.println("================");Object obj21 = Ognl.parseExpression("#d.friends[2]");System.out.println(obj21);Object obj22 = Ognl.getValue(obj21, context, context.getRoot());System.out.println(obj22);System.out.println("================");//处理映射mapObject obj23 = Ognl.parseExpression("#{'key1':'value1','key2':'value2','key3':'value3','key4':'value4'}");System.out.println(obj23);Object obj24 = Ognl.getValue(obj23, context, context.getRoot());System.out.println(obj24);System.out.println("================");Object obj25 = Ognl.parseExpression("#{'key1':'value1','key2':'value2','key3':'value3','key4':'value4'}['key3']");System.out.println(obj25);Object obj26 = Ognl.getValue(obj25, context, context.getRoot());System.out.println(obj26);System.out.println("================");//上一个实例等价于这个实例Object obj27 = Ognl.getValue("#{'key1':'value1','key2':'value2','key3':'value3','key4':'value4'}['key3']", context, context.getRoot());System.out.println(obj27);System.out.println("================");List<Person> list = new ArrayList<Person>();Person p1 = new Person();p1.setName("zhan");Person p2 = new Person();p2.setName("zhangsan222");Person p3 = new Person();p3.setName("zhangsan333");list.add(p1);list.add(p2);list.add(p3);context.put("list", list);//过滤System.out.println(Ognl.getValue("#list.{? #this.name.length() > 4}", context, context.getRoot()));System.out.println("================");System.out.println(Ognl.getValue("#list.{? #this.name.length() > 4}.size()", context, context.getRoot()));System.out.println("================");System.out.println(Ognl.getValue("#list.{^ #this.name.length() > 4}[0].name", context, context.getRoot()));System.out.println("================");System.out.println(Ognl.getValue("#list.{$ #this.name.length() > 4}[0].name", context, context.getRoot()));System.out.println("================");//投影System.out.println(Ognl.getValue("#list.{name}", context, context.getRoot()));System.out.println("================");System.out.println(Ognl.getValue("#list.{#this.name.length() > 4 ? #this.name : 'hello world'}", context, context.getRoot()));}}输出的结果为:namezhangsan================#p.namezhangsan================#d.namewangcai================name.toUpperCase()ZHANGSAN================@java.lang.Integer@toBinaryString(10)1010================@java.lang.Math@min(4, 10)4================new java.util.LinkedList()[]================{ "aa", "bb", "cc" }[aa, bb, cc]================{ "aa", "bb", "cc" }[2]cc================#d.friends[Ljava.lang.String;@3901c6================#d.friends[2]cc================#{ "key1" : "value1", "key2" : "value2", "key3" : "value3", "key4" : "value4" }{key1=value1, key2=value2, key3=value3, key4=value4}================#{ "key1" : "value1", "key2" : "value2", "key3" : "value3", "key4" : "value4" }["key3"]value3================value3================[com.bj.study.ognl.Person@388993, com.bj.study.ognl.Person@1d04653]================2================zhangsan222================zhangsan333================[zhan, zhangsan222, zhangsan333]================[hello world, zhangsan222, zhangsan333]

四、OGNL在Struts2中的应用
1.值栈的概念 OgnlValueStack,是根对象,在Struts2的任何流程中,ValueStack中的最顶层对象一定是Action对象。
2.命名对象:在OGNL Context 中包含有值栈和命名对象,是并列关系;其中命名对象包含parameters、request、session、application和attr
3.访问静态方法或静态成员变量的改进:
    @vs@method    表示访问值栈中的method静态方法
request:<s:property value="#request.hello"/>session:<s:property value="#session.hello"/>application:<s:property value="#application.hello"/>--------------------------------<br>request:<%=((Map)ActionContext.getContext().get("request")).get("hello") %><br>session:<%=((Map)ActionContext.getContext().get("session")).get("hello") %><br>application:<%=((Map)ActionContext.getContext().get("application")).get("hello") %><br>-------------------------------<br/>address:<s:property value="list[0].address" /><br>age:<s:property value="list[1].age" /><br>cat1:name:<s:property value="list[0].cat.name" /><br>-------------------------------<br/>address:<%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get("address") %><br>age:<%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get("age") %><br>cat1:name:<%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get("cat") %><br>
 
4.对于struts2标签中使用OGNL需要注意%与#的关系:
    a.如果标签的属性值是OGNL表达式,那么无需添加%{};eg:<s:property value="ognl表达式"/>
    b.如果标签的属性值是字符串类型,那么在字符串当中凡是出现的%{}都会被解析成OGNL表达式,解析完毕后再与其他的字符串进行拼接造出最后的字符串。eg:<s:a hfef="....?id=%{ognl表达式}"
    c.我们可以在所有的属性值上添加%{},这样如果该属性值是OGNL表达式,则标签处理类就会将%{}忽略掉。

五、执行并等待拦截器ExecuteAndWaitInterceptor
该拦截器需要配置在所有拦截器后

wait页面需添加



原创粉丝点击