Struts2-03-OGNL表达式

1. OGNL 简介

OGNL是Object Graph Navigation Language(对象图形导航语言)的缩写。要学习好struts2标签的取值,首先得先弄清楚ognl表达式的取值原理。OGNL的取值原理其实就是从一个大的ognl上下文(OgnlContext)中,通过相应的表达式语句,对一个对象的属性进行获取或者对方法进行调用。上下文中还包含一个唯一的root对象,root可以通过程序进行指定。

2. OGNL 的简单使用

首先准备示例的类Person和Department,一个Person属于一个Department

public class Person {
    private String name;
    private int age;
    private Department department;
    // getter和setter方法
    // ...
}
public class Department {
    private String name;

    // getter和setter方法
    // ...
}

2.1 设置root和上下文

// 1. 通过setRoot方法进行指定
Ognl.setRoot(Map context, Object root);
// 2. 获取值的时候,通过getValue的重载传入
Ognl.getValue(...)

下面设置root和上下文的时候采用第二种方式。。。其实通过setRoot方法可以看出,OGNL上下文其实就是一个大的Map,然后其中包含一个key为”root”的对象。

2.2 操作简单属性

Person p = new Person();
p.setName("mimosa");
p.setAge(22);

// 获取简单属性name或者age
System.out.println(Ognl.getValue("name", p));
// 或者通过类似js属性获取的方式
System.out.println(Ognl.getValue("['name']", p));

// 输出:
// mimosa

此时的root对象是Person对象p,要是没有指定上下文默认就是一个包含root(p)的上下文Map,然后通过表达式”name”对p中name属性的值进行获取。这里的OGNL结构:
这里写图片描述
下面还有一个就是从root中取值和从ognlContext取值的表达式又是不相同的。
如果表达式中没有以”#”号开通,那么就从根(root)中取值。
如果包含”#”,那么就从上下文中取值。
所以上面获取name的方式还可以改为如下:

System.out.println(Ognl.getValue("#root.name", p));

2.3 操作引用属性

Department d = new Department();                       
d.setName("火星");                                       

Person p = new Person();                               
p.setName("mimosa");                                   
p.setAge(22);                                          
p.setDepartment(d);                                    

// 获取引用的属性值                                            
System.out.println(Ognl.getValue("department.name", p))

// 输出:                                                 
// 火星                         

这里稍微想想就能理解,不多说了。

2.4 设置上下文

Person p1 = new Person();                                
p1.setName("张三");                                        
p1.setAge(20);                                           

Person p2 = new Person();                                
p2.setName("李四");                                        
p2.setAge(30);                                           

// 上下文其实就是一个Map                                          
Map context = new HashMap();                             
context.put("p1", p1);                                   
context.put("p2", p2);                                   

System.out.println(Ognl.getValue("name", context, p1));  
System.out.println(Ognl.getValue("#p1.name", context, p1)
System.out.println(Ognl.getValue("#p2.name", context, p1)

// 输出:                                                   
// 张三                                                    
// 张三                                                    
// 李四                                

刚刚说了,上下文其实就是一个Map,这里getValue第二个参数就是设置上下文,第三个参数是设置根(root)。其实根可以随便指定的,root指向上下文都没有关系,只是要理清楚上下文的结构,那么取值就可以变得十分简单。
通过这里的ognl上下文结构就可以一目了然:
这里写图片描述
然后分析表达式:
1. “name” – 没有”#”号,默认从根(p1)中取值。
2. “#p1.name” – 从上下文中取,Map中key为”p1”的值为Person对象p1。
3. “#p2.name” – 同上。

2.5 调用方法

Person p = new Person();
System.out.println(Ognl.getValue("sayHello('you')", p));

// 输出:
// hello you

ognl比较强大的地方就是支持方法的调用。

2.6 操作集合或数组

操作集合和数组当然需要借助索引进行获取。

Person p1 = new Person();                              
p1.setName("张三");                                      
p1.setAge(20);                                         

Person p2 = new Person();                              
p2.setName("李四");                                      
p2.setAge(30);                                         

List list = new ArrayList();                           
list.add(p1);                                          
list.add(p2);                                          

System.out.println(Ognl.getValue("[0].name", list)); 
// 或者  
System.out.println(Ognl.getValue("#root[0].name", list)

// 输出:                                                 
// 张三                                                  
// 张三      

数组与之类似。但是想到上面可以进行方法的调用,那么List的get方法是否还会起作用?答案是肯定的。
// 这样依然可以获取

System.out.println(Ognl.getValue("get(0).name", list));

2.7 调用静态方法或属性

使用两个”@”符号对静态方法进行调用,第一个@后面跟类的前面,第二个@后面跟静态方法或者静态属性。
这里特别注意的是如果是java.lang.Math类,那么第一个@后面可以不跟东西。

System.out.println(Ognl.getValue("@java.lang.Math@max(1,2)", null)); // 2
System.out.println(Ognl.getValue("@@max(1,2)", null)); // 2
System.out.println(Ognl.getValue("@@PI", null)); // 3.141592653589793

2.8 映射集合或者Map

通过表达式 “{1,’ss’,20}” 可以映射出一个ArrayList集合。

System.out.println(Ognl.getValue("{1,'ss',20}[1]", null)); // ss

通过表达式 “#{‘key1’:2,’key2’:’ss’}” 可以映射出一个 LinkedHashMap,注意 “#” 开头。

System.out.println(Ognl.getValue("#{'key1':2,'key2':'ss'}.key1", null)); // 2
System.out.println(Ognl.getValue("#{'key1':2,'key2':'ss'}['key2']", null)); // ss

3. 其他表达式

3.1 过滤表达式

过滤是针对集合进行处理的,表达式为:coloection.{?expression}

Person p1 = new Person();
p1.setName("张三");
p1.setAge(20);

Person p2 = new Person();
p2.setName("李四");
p2.setAge(30);

List list = new ArrayList();
list.add(p1);
list.add(p2);

System.out.println(Ognl.getValue("#root.{?#this.age>=30}", list));

// 过滤出年龄大于等于30的对象

这里的代码筛选出了p2,返回类型是一个集合。”#this”表示当前处理的对象。

也可以通过表达式 coloection.{^expression} 来对集合第一个元素进行处理,通过coloection.{$expression} 来对集合最后一个元素进行处理。

3.2 投影

也可以通过这种表达式 coloection.{expression} 进行更加复杂的操作。

// 投影出name属性, 返回一个集合
System.out.println(Ognl.getValue("#root.{name}", list)); // [张三, 李四]
// 对投影的值进行筛选, 注意{}开头没有"?"号
System.out.println(Ognl.getValue("#root.{#this.age>=30?'gt30':#this.age}", list)); // [20, gt30]

4. 总结

综上ognl表达式确实比较强大,但是也简单易懂。在struts2标签中获取想要的值的时候,无非也就是从大的ognl上下文中去获取,所以在学习标签之前要对ognl表达式有一定的了解。最后附上struts2中ognl大致的结构图:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值