表达式处理
曾经在一个项目中使用表达式来判断处理一些条件,比如订单价格的折扣计算,库存数量的告警线设置等。我们引入了Jexl(一种表达式语言引擎)来处理这些表达式。这里根据几个例子来总结一下它的应用。
例一、算式表达式的处理:
public class jextTest {
public static void main(String[] args) {
//数学公式解析和计算
String expression = "(a+b)/c*5";
JexlContext jexlContext = new MapContext();
jexlContext.set("a", 4);
jexlContext.set("b", 2);
jexlContext.set("c", 2);
jexlContext.set("d", 5);
Expression e = (Expression) new JexlEngine().createExpression(expression);
Number num = (Number) e.evaluate(jexlContext);
System.out.println(num);
expression = "a || b && c || d";
jexlContext = new MapContext();
jexlContext.set("a", true);
jexlContext.set("b", false);
jexlContext.set("c", true);
jexlContext.set("d", false);
org.apache.commons.jexl2.Expression e1 = new JexlEngine().createExpression(expression);
Boolean num1 = (Boolean) e1.evaluate(jexlContext);
System.out.println(num1);
JexlEngine jexl = new JexlEngine();
jexl.setCache(512);//Sets a cache for expressions of the defined size
jexl.setLenient(false);//Sets whether this engine considers unknown variables, methods and constructors as errors or evaluates them as null or zero.
jexl.setSilent(false); //Sets whether this engine throws JexlException during evaluation when an error is triggered.
jexl.setStrict(false); //Sets whether this engine behaves in strict or lenient mode.
String calculate = "(a + b) > 10";
e = jexl.createExpression(calculate);
JexlContext context = new MapContext();
context.set("a", "3");
context.set("b", "5");
Object res = e.evaluate(context);//silent为false时evaluate方法会抛异常,为true不抛异常但res为null
System.out.println(res);
}
}
运行结果如下:
15
true
false
从上例中可以看出,实现一个表达式的解析运算,共涉及到三个主要类:JexlContext、Expression和JexlEngine。
例二、数组取值
ublic class ArrayTest {
public static void main(String[] args) {
JexlEngine jexl = new JexlEngine();
JexlContext jc = new MapContext();
List l = new ArrayList();
l.add("It is from location 0");
Integer two = new Integer(2);
l.add(two);
jc.set("array", l);
Expression e = jexl.createExpression("array[1]");//从array中取数据
Object o = e.evaluate(jc);
System.err.println("Object @ location 1 = " + o);
e = jexl.createExpression("array[0]");//从array中取数据
o = e.evaluate(jc);
System.err.println("Object @ location 0 = " + o);
e = jexl.createExpression("array[0].length()");
o = e.evaluate(jc);
System.err.println("The length of the string at location 0 is :" + o);
}
}
运行结果如下:
Object @ location 1 = 2
Object @ location 0 = It is from location 0
The length of the string at location 0 is :21
例三、取方法运行
public class MethodPropertyTest {
public static void main(String[] args) {
JexlEngine jexl = new JexlEngine();
JexlContext jc = new MapContext();
MethodPropertyTest foo = new MethodPropertyTest();
Integer number = new Integer(10);
jc.set("foo", foo);
jc.set("number", number);
Expression e = jexl.createExpression("foo.getFoo()");
Object o = e.evaluate(jc);
System.err.println("value returned by the method getFoo() is : " + o);
e = jexl.createExpression("foo.convert(1)");
o = e.evaluate(jc);
System.err.println("value of " + e.getExpression() + " is : " + o);
e = jexl.createExpression("foo.convert(1+7)");
o = e.evaluate(jc);
System.err.println("value of " + e.getExpression() + " is : " + o);
e = jexl.createExpression("foo.convert(1+number)");
o = e.evaluate(jc);
System.err.println("value of " + e.getExpression() + " is : " + o);
e = jexl.createExpression("foo.bar");
o = e.evaluate(jc);
System.err.println("value returned for the property 'bar' is : " + o);
}
public String getFoo() {
return "This is from getFoo()";
}
public String get(String arg) {
return "This is the property " + arg;
}
public String convert(long i) {
return "The value is : " + i;
}
}
运行结果如下:
value returned by the method getFoo() is : This is from getFoo()
value of foo.convert(1) is : The value is : 1
value of foo.convert(1+7) is : The value is : 8
value of foo.convert(1+number) is : The value is : 11
value returned for the property 'bar' is : This is the property bar
表达式的处理也可以集成Groovy来处理。相比Jexl来讲,Groovy的功能更强大。