同步操作将从 eric_1989/jfireEL 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
EL 表达式解析,在一些涉及到动态规则配置的场合使用较多。比如工作流引擎中的外部规则注入,比如 Spring 框架中的 SpEL 解析等等。jfireEL 框架支持常见的 EL 表达式,诸如四则运算,数组元素获取,链表元素获取,Map 键值对获取,属性获取,方法调用,级联调用,支持获取类定义,枚举定义,支持获取对象等等。
相比于 SpringEL,jfireEL 在表达上更为简洁,比如对于 SpringEL,一个变量属性级联对比的表达式可以写为vars['home'].bool(vars['person'].getAge() + '12' != vars['value'])
,而jfireEL 的写法直接为home.bool(person.getAge() + '12' != value)
。显然 jfireEL 的可读性更高。
欢迎加入技术交流群186233599讨论交流,也欢迎关注笔者公众号:风火说。
使用 EL 表达式vars['home'].bool(vars['person'].getAge() + '12' != vars['value'])
对jfireEL,BeetlEL,SpringEL 三款框架进行性能对比验证。在进入测试之前均预热相同次数确保初始化完毕。三款框架性能对比如下
首先引入Maven依赖,如下
<dependency>
<groupId>com.jfirer</groupId>
<artifactId>jfireEl</artifactId>
<version>1.0</version>
</dependency>
在代码中使用时,首先进行EL 表达式的解析,而后使用这个外部参数就可以对表达式进行求值。
int[] array = new int[]
{
1, 2, 3, 4
};
Map < String, Object > vars = new HashMap < String, Object > ();
vars.put("array", array);
Expression lexer = Expression.parse("array[2]");//使用静态方法parse解析字符串形式的EL表达式,得到一个表达式实例。该表达式是一个并发安全的实例,可以供后续反复的并发的调用。一次生成即可,无需反复生成。
assertEquals(3, lexer.calculate(vars));//外部参数通过Map的形式传递。使用方法calculate根据给定的参数计算得到表达式的值
在 EL 表达式中,如果一个字符串使用''
进行包围,则被认为是一个字符串;否则的话,可以被认定为变量名,方法名,参数名,具体某个枚举的名称,视上下文的情况而定。
jfireEL 使用 Map 作为参数的载体,其 Key 的值就是变量名,value 对应的就是变量值。
具体的代码使用方法可以参见如下示例。
jfireEL 支持使用[]
对数组元素,List,Map进行属性的获取,比如下面的表达式都是正确且合法的。
获取数组元素
int[] array = new int[]
{
1, 2, 3, 4
};
Map < String, Object > vars = new HashMap < String, Object > ();
vars.put("array", array);
Expression lexer = Expression.parse("array[2]"); //EL 表达式解析
assertEquals(3, lexer.calculate(vars)); //EL 表达式执行
获取List中元素
List < String > list = new ArrayList < String > ();
list.add("1212");
list.add("13");
Map < String, Object > vars = new HashMap < String, Object > ();
vars.put("list", list);
Expression lexer = Expression.parse("list[1]");
assertEquals("13", lexer.calculate(vars));
获取Map键值
Map < String, String > map = new HashMap < String, String > ();
map.put("1", "12");
Map < String, Object > vars = new HashMap < String, Object > ();
vars.put("map", map);
vars.put("age", "1");
Expression lexer = Expression.parse("map['1']");
assertEquals("12", lexer.calculate(vars));
Expression lexer2 = Expression.parse("map[age]");
assertEquals("12", lexer2.calculate(vars));
四则运算,加减乘除,求余的支持如下
Expression lexer = Expression.parse("1+4/2");
assertEquals(3, lexer.calculate(null)); //对于不需要注入参数计算的场合,入参可以直接为null,不影响运算
Expression lexer = Expression.parse("5-(4-1)");
assertEquals(2, lexer.calculate(null));
Expression lexer = Expression.parse("1*2-1");
assertEquals(1, lexer.calculate(null));
支持使用.
进行对象属性获取。而如果要获取静态类的属性,支持使用T(ClassName)
的形式获取静态类,再使用.
来获取对应的属性。两者的代码如下
public class PropertyTest extends TestSupport
{
public static int age = 12;
//对象属性获取
@Test
public void test()
{
Expression lexer = Expression.parse("home.person.age");
//home 是一个对象,包含一个对象属性 person,age是person中的一个数字属性
assertEquals(person.age, lexer.calculate(vars));
lexer = Expression.parse("home.person.age", Functional.build().setPropertyFetchByUnsafe(true).setRecognizeEveryTime(false).toFunction());
assertEquals(person.age, lexer.calculate(vars));
}
//类属性获取
@Test
public void test2()
{
//PropertyTest 就是测试类本身,使用T()包围表明这是一个类的全限定名
int result = Expression.parse("T(PropertyTest).age").calculate();
assertEquals(age, result);
}
}
上面的对象属性获取可以看到,jfireEL 框架支持级联操作。
jfireEL 支持 expression?value1:value2 这种形式的三元表达式,具体代码如下
assertEquals(1, Expression.parse("2>1?1:2").calculate());
assertEquals(1, Expression.parse("3-2+1>1?1:2").calculate());
assertEquals(1, Expression.parse("3-2+1>1?2-1:2").calculate());
assertEquals(2, Expression.parse("3-2+1<1?2:1+1").calculate());
Map < String, Object > vars = new HashMap < String, Object > ();
Map < String, Object > param = new HashMap < String, Object > ();
param.put("b", false);
vars.put("map", param);
assertEquals(2, Expression.parse("map['b']?3:1*2").calculate(vars));
assertEquals(4, Expression.parse("(map['b']?3:2)*2").calculate(vars));
方法调用也是使用.
作为开始符号,和属性获取不同的是,其需要使用()
作为结束符号,并且可以根据情况,支持入参填入。具体代码如下
Expression lexer = Expression.parse("home.person.getAge()");
assertEquals(person.age, lexer.calculate(vars));
Expression lexer = Expression.parse("home.personAge2(person.getAge()+2)");//方法调用支持入参,并且支持在入参中执行计算
assertEquals(person.getAge() + 2, lexer.calculate(vars));
jfireEL 支持获取具体的枚举实例,也获取类属性的方式相同,代码如下
public class EnumTest
{
enum Name
{
dd;
}
@Test
public void test()
{
Expression lexer = Expression.parse("T(EnumTest$Name).dd");
assertEquals(Name.dd, lexer.calculate());
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。