Java Expression Language (JEXL) 是一个表达式语言引擎,可以用来校验数据。
背景
项目中,需要配置一些规则,然后根据动态的数据去验证规则。比如配置如下的规则:
或者这种
计算方式需要通过配置来完成,使用这个方式就非常便捷了。
案例:
人数大于5,并且名称包含 “test” 才能验证通过。
按照传统的思路,一般就是写死代码,如:
if(num > 5 && name.contains("test")){
return true;
}
但是,如果规则变成了人数等于6,那就要去修改代码(虽然值可以动态获取,但是 > 不能动态改为 = ),比较麻烦。那么就换一种思路,做成可以配置的,按照上面的规则,就是配置成:
纬度1 公式1 值1 && 纬度2 公式2 值2
${num} > 5 && ${name}.contains(“test”)
在为变量设置具体值。
10 > 5 && “test jexl”.contains(“test”)
那么问题来了,怎么动态验证这个表达式的结果呢?
为了计算上面表达式的结果,这时候就需要用到 JEXL 了,我们直接看代码。
org.apache.commons
commons-jexl3
3.1
JexlContext jc = new MapContext();
JexlExpression expression = new JexlBuilder().create().createExpression("10 > 5 && \"test jexl\".contains(\"test\")");
Object result = expression.evaluate(jc);
System.out.println(result);
运行结果为:true
1 > 5 && “test jexl”.contains(“test”)
JEXL 也可以通过设置参数来计算结果,比如公式为:x - y
那么我们可以通过 JEXL 来设置 x 和 y 的值。
JexlContext jc = new MapContext();
jc.set("x", 10);
jc.set("y", 20);
JexlExpression e = new JexlBuilder().create().createExpression("x - y");
Object result = e.evaluate(jc);
System.out.println(result);
运行结果为:-10
这边有个容易出错的地方,jc.set()第二个参数为 object 类型,需要根据实际类型来传值(比如值为 string 的时候需要带引号),否则可能会报错。
首先写一个公共方法:
public class Util {
public static boolean regMatch(String regEx, String str) {
Pattern pattern = Pattern.compile(regEx);
return pattern.matcher(str).matches();
}
}
下面是使用JEXL调用的方法
public void RL() {
JexlContext jc = new MapContext();
String str = "一二三四五六七八九十";
jc.set("Util", new Util());
jc.set("str", str);
jc.set("ans", "");
String expression = "ans = Util.regMatch(\"[\u4e00-\u9fa5]{10,}\",str)";
Expression e = new JexlEngine().createExpression(expression);
e.evaluate(jc);
System.out.println(jc.get("ans"));
}
循环
JEXL支持两种循环方式:
for(item : list) {
x = x + item;
}
while (x lt 10) {
x = x + 2;
}
在JDK1.6之后内部也支持使用ScriptEngine,功能也很强大,针对ScriptEngine我有另外一篇博客,感兴趣的可以去看下
先介绍上面几个陌生的类:
MapContext
JexlBuilder
方法:
createExpression
evaluate
本文摘自:https://blog.csdn.net/qqfo24/article/details/88252313 https://blog.csdn.net/u012468264/article/details/56679802