Java有许多开源的表达式解析器。以下是一些常用的选项:
JEXL: JEXL (Java Expression Language) 是一个用于解析和评估表达式的库。它允许你动态地评估复杂的表达式。
GroovyShell: <计算器>
OGNL: OGNL (Object-Graph Navigation Language) 是一个强大的表达式语言,用于在对象图上执行导航、查找和操作。
Jandex: Jandex 是另一个用于解析和评估表达式的库,它特别适用于处理与注解相关的表达式。
MVEL: MVEL (Model-driven Value Expression Language) 是一个动态的表达式语言,用于在运行时解析和评估复杂的表达式。
Apache Commons Lang: Apache Commons Lang 提供了一些用于处理字符串的实用工具,其中也包括表达式解析。
1、使用 JEXL演示:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl3</artifactId>
<version>3.1</version>
</dependency>
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlException;
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.MapContext;
public static class JexlExample {
public static void main(String[] args) {
// 创建 JEXL 表达式
String expression = "array.size() > 0 || str.contains(\"苹果\")";
// 创建 JEXL 上下文(可以传递变量和函数)
JexlContext jexlContext = new MapContext();
jexlContext.set("array", new ArrayList<>());
jexlContext.set("str", "小苹果");
// 创建 JEXL 表达式对象
JexlExpression jexlExpression = new JexlBuilder()
.create()
.createExpression(expression);
// 评估表达式并获取结果
Object result = jexlExpression.evaluate(jexlContext);
// 输出结果
System.out.println("Result: " + result); // 输出: Result: 6
}
}
2、使用GroovyShell 演示:
/**
* groovy 计算器
* @Date 2022/3/22 11:52
*/
public class Groovy {
static String EQUATION1 = "(a+b)=(c+d)";
static String EQUATION2 = "(1+2)=(3+4)";
public static void main(String[] args) {
//(1)执行groovy脚本
GroovyShell groovyShell1 = new GroovyShell();
groovyShell1.evaluate("println 'hello world'"); // hello world
//(2)groovy计算器
Binding binding2 = new Binding();
binding2.setVariable("a", BigDecimal.valueOf(1000));
binding2.setVariable("b", BigDecimal.valueOf(1));
binding2.setVariable("c", BigDecimal.valueOf(2));
GroovyShell groovyShell2 = new GroovyShell(binding2);
//计算值
Object result = groovyShell2.evaluate("(a+b)*c");
System.out.println("(a+b)*c = " + result); // (a+b)*c = 2002
//(3)groovy判断等式是否相等
Binding binding = new Binding();
//变量前缀: 解决变量是数字会被shell直接解析不会替换值 binding.setVariable("1", "a") -> binding.setVariable("p_1", "a");
String prev = "p_";
binding.setVariable(prev + "1", BigDecimal.valueOf(1000));
binding.setVariable(prev + "2", BigDecimal.valueOf(500));
binding.setVariable(prev + "3", BigDecimal.valueOf(2000));
binding.setVariable(prev + "4", BigDecimal.valueOf(2000));
GroovyShell groovyShell3 = new GroovyShell(binding);
//结合正则表达式, 替换时添加变量前缀p_
Map<String, String> prop2Name = Maps.newHashMap();
prop2Name.put("1", "A");
prop2Name.put("2", "B");
prop2Name.put("3", "C");
prop2Name.put("4", "D");
String[] split = EQUATION2.split("=");
//左等式值
BigDecimal leftValue = (BigDecimal) groovyShell3.evaluate(ReUtil.replaceAll(split[0], "\\d{1,2}", matcher -> prev + matcher.group())); // \d{1,2} 匹配最大十位的整数
//右等式值
BigDecimal rightValue = (BigDecimal) groovyShell3.evaluate(ReUtil.replaceAll(split[1], "\\d{1,2}", matcher -> prev + matcher.group()));
//左等式中文
String leftName = ReUtil.replaceAll(split[0], "\\d{1,2}", matcher -> prop2Name.get(matcher.group()));
//右等式中文
String rightName = ReUtil.replaceAll(split[1], "\\d{1,2}", matcher -> prop2Name.get(matcher.group()));
//等式中文
String finalEqu = leftName + "=" + rightName;
//判断等式是否相等
System.out.println(finalEqu + (leftValue.compareTo(rightValue) == 0 ? " 成立" : "不成立"));
// (A+B)=(C+D)不成立
}
}