由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。 它是线程安全的,引擎运算过程中产生的临时变量都是ThreadLocal类型。
- 支持 +、-、*、/、<、>、<=、>=、==、!=、<>、%、mod、++等
- in、like(sql语法)、&&、||、!
- 支持for、break、continue、if then else 等标准的程序控制逻辑
- 三元运算符
- 属于弱类型语言,不能定义类型声明,更不能用Templete(Map<String,List>等)。
- 不支持Lambda表达式。
QLExpress主要通过子类实现Operator提供的executeInner() 来进行操作符定义,然后可以通过addFunction或addOperator注入到ExpressRunner中。
ExpressRunner runner = new ExpressRunner();
// 关键字替换
runner.addOperatorWithAlias("如果", "if", null);
runner.addOperatorWithAlias("则", "then", null);
runner.addOperatorWithAlias("否则", "else", null);
// QL 表达式
String exp = "如果 (语文+数学+英语>270) 则 {return 1;} 否则 {return 0;}";
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
runner.execute(exp,context,null,false,false,null);
- runner.addOperator(“join”, new JoinOperator());:添加操作符号,可以设置优先级。
- runner.replaceOperator("+", new JoinOperator());:替换操作符处理。
- runner.addFunction(“join”, new JoinOperator());:通过自定义的Operator来实现函数。
//定义一个继承自 Operator 的操作符
public class JoinOperator extends Operator{
public Object executeInner(Object[] list) throws Exception {
Object opdata1 = list[0];
Object opdata2 = list[1];
if(opdata1 instanceof List){
((List)opdata1).add(opdata2);
return opdata1;
}else{
List result = new ArrayList();
result.add(opdata1);
result.add(opdata2);
return result;
}
}
}
// 使用
// addOperator()——返回结果:[1, 2, 3]
ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
// 传入自定义的 Operator
runner.addOperator("join",new JoinOperator());
Object r = runner.execute("1 join 2 join 3", context, null, false, false);
System.out.println(r);
public class BeanExample {
public static String upper(String abc) {
return abc.toUpperCase();
}
public boolean anyContains(String str, String searchStr) {
char[] s = str.toCharArray();
for (char c : s) {
if (searchStr.contains(c + "")) {
return true;
}
}
return false;
}
}
ExpressRunner runner = new ExpressRunner();
runner.addFunctionOfClassMethod("取绝对值", Math.class.getName(), "abs", new String[] { "double" }, null);
runner.addFunctionOfClassMethod("转换为大写", BeanExample.class.getName(), "upper", new String[] { "String" }, null);
runner.addFunctionOfServiceMethod("打印", System.out, "println",new String[] { "String" }, null);
runner.addFunctionOfServiceMethod("contains", new BeanExample(), "anyContains", new Class[] { String.class, String.class }, null);
String exp = “取绝对值(-100);转换为大写(\"hello world\");打印(\"你好吗?\");contains("helloworld",\"aeiou\")”;
runner.execute(exp, context, null, false, false);
runner.addMacro("计算平均成绩", "(语文+数学+英语)/3.0");
runner.addMacro("是否优秀", "计算平均成绩>90");
IExpressContext<String, Object> context =new DefaultContext<String, Object>();
context.put("语文", 88);
context.put("数学", 99);
context.put("英语", 95);
Object result = runner.execute("是否优秀", context, null, false, false);
System.out.println(r);
// 执行一段文本
Object execute(String expressString, // 程序文本
IExpressContext<String,Object> context, // 执行上下文,可以扩展为包含 ApplicationContext
List<String> errorList, // 输出的错误信息 List
boolean isCache, // 是否使用 Cache 中的指令集,建议为 true
boolean isTrace, // 是否输出详细的执行指令信息,建议为 false
Log aLog. // 输出的 log
);
ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
context.put("a",1);
context.put("b",2);
context.put("c",3);
String express = "a+b*c";
Object r = runner.execute(express, context, null, true, false);
System.out.println(r);