type
status
date
slug
summary
tags
category
icon
password

I. 基本使用

1. 配置

我们选用的是java开发环境,使用maven来进行包管理,首先在pom文件中添加依赖

2. 基础使用

对于Ognl的使用,关键的地方在于获取OgnlContext, 在这个上下文中保存一些实例用来支撑ognl的语法
所以一般使用ognl的先前操作就是创建OgnlContext,然后将我们的实例扔到上下文中,接收ognl表达式,最后执行并获取结果

II. 实例演示

接下来进入实例演示,首先我们需要创建两个测试对象,用于填充OgnlContext

0. 准备

两个普通对象,一个静态类
上面在创建OgnlContext时,有一个DefaultMemberAccess类,主要用于设置成员的访问权限,需要自己实现
接下来创建我们的OgnlContext对象
到此,我们的前置准备已经就绪,接下来进入实际case篇

1. 实例访问

我们的实例访问分为两类,分别为实例的方法调用;实例的属性访问

a. 实例方法调用

比如我们希望执行 print的sayHello方法,可以如下使用
关键点在ognl表达式: #print.sayHello("一灰灰blog", 18),其中print为实例名,对应的构建OgnlContext对象之后执行的context.put("print", print);这一行代码
输出结果:

b. 实例成员属性访问

成员属性的访问可以划分为直径获取成员属性值和设置成员属性值,对此可以如下使用
输出结果
看到上面这个,自然会想到一个问题,可不可以访问父类的私有成员呢?
为了验证这个问题,我们新建一个实例继承自ADemo,并注册到 OgnlContext 上下文
输出结果如下
注意:
我们这里可以直接访问私有成员,访问私有方法,访问父类的私有成员,这些都得益于我们自定义的DefaultMemberAccess,并制定了访问策略为true(即私有、保护、默认访问权限的都可以访问)

2. 静态类访问

实例成员,需要先注册到OgnlContext之后才能根据实例名来访问,但是静态类则不需要如此,默认支持当前的ClassLoader加载的所有静态类的访问姿势;下面我们进入实例演示

a. 静态类方法调用

静态类的访问需要注意的是需要传入全路径,用@开头,类与方法之间也是用@进行分割
输出结果

b. 静态类成员访问

同样我们分为成员访问和修改
输出结果如下
直接设置静态变量,抛出了移仓,提示InappropriateExpressionException
那么静态类的成员可以修改么?这里先留一个疑问

3. 特殊传参

一般的java操作,无外乎方法调用,属性访问两种,接下来我们聚焦在方法的调用上;如果一个方法接收的参数是一些基本类型的对象,使用起来还比较简单;但是其他的场景呢?

a. class类型参数

如我们前面的PrintDemo中,有一个方法如下
如需调用上面的方法,clz参数可以怎么处理呢?
上面给出了两种方式,一个是根据已有的对象获取class,一个是直接根据静态类获取class,输出结果如下

b. 枚举参数

如PrintDemo中的方法, 其中第二个参数为枚举
结合上面的使用姿势,这个也不太难
输出结果

c. null传参

目标方法如下
因为我们需要传参为空对象,稍微有点特殊,ognl针对这个进行了支持,传参直接填null即可
输出如下
然后一个问题来了,在PrintDemo中的print方法,有多个重载的case,那么两个参数都传null,具体是哪个方法会被执行呢?
通过实际的测试,第三个方法被调用了,这里面难道有啥潜规则么,然而我并没有找到
输出

d. 对象传递

传参是一个POJO对象,这个时候咋整?
现在的问题主要集中在如何构建一个Aemo对象,当做参数丢进去,通过前面的语法篇我们知道ognl是支持new来创建对象的, 如果ADemo恰好提供了全属性的构造方法,那么可以如下操作
注意观察上面的ognl表达式,其中重点在new git.hui.fix.test.ognl.bean.ADemo("test", 20)),创建对象的时候,请指定全路径名
输出结果
上面这个虽然实现了我们的case,但是有局限性,如果这个POJO没有全属性的构造方法,又可以怎么整?
这里就需要借助ognl语法中的链式语句了,通过new创建对象,然后设置属性,最后抛出对象
核心语句在(#demo=new git.hui.fix.test.ognl.bean.ADemo(), #demo.setName(\"一灰灰\"), #demo),创建对象,设置属性
输出结果
虽说上面实现了我们的需求场景,但是这里有个坑,我们创建的这个属性会丢到OgnlContext上下文中,所以这种操作非常有可能导致我们自己创建的临时对象覆盖了原有的对象
那么有什么方法可以避免么?
这个问题先攒着,后面再叙说

e. 容器传参

在PrintDemo对象中添加方法
然后我们的访问case如下
输出结果

4. 表达式执行

接下来属于另外一个范畴的case了,执行一些简单的算术操作or条件表达式
输出

III. 小结

鉴于篇幅过长,本篇博文将只限于使用基础的ognl能支持到什么地步,在java中使用ognl套路比较简单

1. 创建OgnlContext,并注册实例

2. 编译ognl表达式,并获取执行结果

参考

线上问题排查:CPU突然飙升如何处理Ognl语法基础教程
mcbilla
mcbilla
一个普通的干饭人🍚
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎来到飙戈的博客🎉
-- 感谢您的支持 ---
👏欢迎学习交流👏