Java 表达式执行引擎 jexl
介绍
JEXL的全称是Java表达式语言(Java Expression Language),简单的说,它可以配合我们的Java程序运算一些简单的表达式。
具体可以识别哪些表达式?
包含最基本的加减乘除、大于小于等于、与或非、按位与、按位或、按位异或、按位补码;
除此之外还可以调用Java程序中方法,比如要判断一个字符串是否包含某一个字符。
引入依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl</artifactId>
<version>2.1.1</version>
</dependency>
基本实现步骤
// 创建表达式引擎对象
JexlEngine engine = new JexlEngine();
// 创建表达式语句
String expressionStr = "money > 5000";
// 创建Context对象,为表达式中的未知数赋值
JexlContext context = new MapContext();
context.set("money","10000");
// 使用表达式引擎创建表达式对象
Expression expression = engine.createExpression(expressionStr);
// 使用表达式对象计算
Object evaluate = expression.evaluate(context);
// 输出结果:true
System.out.println(evaluate);
常见应用场景
// 判断提交时间是否大于某一个时间点
String expressionStr = "submitTime.getTime() >= 1583856000000";
context.set("submitTime",new Date());
// 判断字符串是否包含“成功”
String expressionStr = "text.contains('成功')";
context.set("text","请求成功");
// 判断字符串是否为空
String expressionStr = "text eq null || text.size() == 0"
// 判断是否属于数组中的任意一个
String expressionStr = "text =~ ['请求成功','啦啦','吧啦吧啦']"
// 判断是否不属于数组中的任意一个
String expressionStr = "text !~ ['请求成功','啦啦','吧啦吧啦']"
// 表达式为逻辑语句,运算结果为:2
String expressionStr = "if(a>b){c=a;}else{c=b};";
context.set("a", 1);
context.set("b", 2);
// 表达式为对象调用方法
String expressionStr = "person.getName()";
Person person = new Person();
person.setName("Sixj");
context.set("person", person);
Java代码示例
package com.cn.utils;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.commons.jexl2.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
public class FormulaConversionUtil {
private static final Logger logger = LoggerFactory.getLogger(FormulaConversionUtil.class);
private static final JexlEngine JEXL = new JexlEngine();
static {
JEXL.setCache(512);
JEXL.setLenient(false);
JEXL.setSilent(false);
}
public static void main(String[] args) {
// 逻辑表达式
String threshold = "(value==3) or (cpu>90 and mem <70)";
Map<String,Object> map = new HashMap<>();
map.put("value", 3);
map.put("cpu", 12);
map.put("mem", 100);
boolean bol = expression(threshold,map);
System.out.println(bol);
// 反向解析表达式中的变量
List<String> variables = getVariables(threshold);
System.out.println(variables);
// 计算表达式
map = new HashMap<>();
map.put("x", 3);
map.put("y", 5);
System.out.println("计算结果:" + calWithJexlEngine("if(1>2) 2*x+y*6 else 3+4",map));
calWithScriptEngine();
}
public static void calWithScriptEngine(){
//创建if执行语句
String expStr1 = "if(a>b){c=a;}else{c=b;}";
Script script1 = JEXL.createScript(expStr1);
JexlContext context1 = new MapContext();
context1.set("a", 1);
context1.set("b", 2);
context1.set("c", 0);
Object obj1 = script1.execute(context1);
System.out.println(obj1);
//创建while执行语句
String expStr2 = "while(a<b){a=a+b;}";
Script script2 = JEXL.createScript(expStr2);
JexlContext context2 = new MapContext();
context2.set("a", 1);
context2.set("b", 2);
Object obj2 = script2.execute(context2);
System.out.println(obj2);
}
/**
* 通用逻辑表达式
* @param expression 表达式
* @param map 参数,允许为Null
* @return
*/
public static boolean expression(String expression,Map<String,Object> map) {
try {
Expression exp = JEXL.createExpression(expression);
JexlContext jc = new MapContext();
if(map != null){
for (String key : map.keySet()){
jc.set(key, map.get(key));
}
}
Object evaluate = exp.evaluate(jc);
if (evaluate instanceof Boolean) {
return (boolean) evaluate;
} else {
logger.error("表达式错误{},不是boolean返回值:{}", exp, evaluate);
return false;
}
} catch (Throwable t) {
logger.error("表达式{}配置错误{}", expression, t.getMessage(), t);
return false;
}
}
/**
* 公式计算表达式
* @param exp 公式 . 如 (a+b-c)*d/f
* @param map 参数集合
* @return 返回结果默认String
*/
public static String calWithJexlEngine(String exp,Map<String , Object> map){
try {
Expression expression = JEXL.createExpression(exp);
JexlContext jc = new MapContext();
if(map != null){
map.keySet().forEach(k->{
//jexl计算结果类型根据入参决定:
//如果参数都是int/Integer类型 . 那么即便结果值应该是4.8 . 返回值也是4 .所以这里为保证计算精度 . 入参可全部以decimal类型处理下
//若参数中存在小数,则结果精度相对准确 . 出参为double类型
Object paramVal = map.get(k);
String paramValStr = paramVal != null ? String.valueOf(paramVal) : "0";
jc.set(k , new BigDecimal(paramValStr));
});
}
Object result =expression.evaluate(jc);
DecimalFormat decimalFormat = new DecimalFormat("0.00");
return decimalFormat.format(result);
} catch (Exception e) {
logger.error("表达式{}配置错误{}", exp, e.getMessage(), e);
return null;
}
}
/**
* 获取表达式中的变量参数
*
* @param expression 表达式,如 ping.max>0 and ping.min>0 and pin.lost==0
*/
public static List<String> getVariables(String expression) {
Expression exp;
try {
exp = JEXL.createExpression(expression);
} catch (Throwable t) {
logger.error("表达式{}配置错误{}。", expression, t.getMessage(), t);
return Collections.emptyList();
}
return getVariables(exp);
}
public static List<String> getVariables(Expression exp) {
List<String> metricDefIds = Lists.newArrayList();
Set<List<String>> variables = JEXL.getVariables((ExpressionImpl) exp);
for (List<String> var : variables) {
metricDefIds.add(Joiner.on(".").join(var));
}
return metricDefIds;
}
}
Java 表达式执行引擎 jexl的更多相关文章
- Java虚拟机执行引擎
执行引擎 关于执行引擎相关的部分, 在之前的博文里 Java内存区域中已经有所提及. 回顾一下: 也只有几个概念, JVM方法调用和执行的基础数据结构是 栈帧, 是内存区域中 虚拟机栈中的栈元素, 每 ...
- jvm虚拟机---执行引擎子系统
Java虚拟机只与Class文件相关联,它规定了Class文件应该具有的格式,而不论该文件是由什么语言编写并编译而来.所以,任何语言只要能够最终编译成符合Java虚拟机要求的Class文件,就可以运行 ...
- 表达式语言引擎:Apache Commons JEXL 2.1 发布
http://www.linuxde.net/2011/12/4348.html Commons JEXL 2.1 发布了,该版本和 2.0.1 是二进制兼容的,但源码不兼容,因为新增了两个接口: o ...
- Java | 在 Java 中执行动态表达式语句: 前中后缀、Ognl、SpEL、Groovy、Jexl3
在一些规则集或者工作流项目中,经常会遇到动态解析表达式并执行得出结果的功能. 规则引擎是一种嵌入在应用程序中的组件,它可以将业务规则从业务代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业 ...
- 《深入理解Java虚拟机》-----第8章 虚拟机字节码执行引擎——Java高级开发必须懂的
概述 执行引擎是Java虚拟机最核心的组成部分之一.“虚拟机”是一个相对于“物理机”的概念 ,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而 ...
- Java 实现String语句的执行(Jexl)
https://www.jianshu.com/p/1000719e49fa 1.maven 导入库 <dependency> <groupId>org.apache.comm ...
- Java虚拟机-字节码执行引擎
概述 Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,成为各种虚拟机执行引擎的统一外观(Facade).不同的虚拟机引擎会包含两种执行模式,解释执行和编译执行. 运行时帧栈结构 栈帧(Sta ...
- Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx
Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\Java ...
- 深入理解java虚拟机(5)---字节码执行引擎
字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...
- 《深入理解Java虚拟机》学习笔记之字节码执行引擎
Java虚拟机的执行引擎不管是解释执行还是编译执行,根据概念模型都具有统一的外观:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 栈帧(Stack Frame) ...
随机推荐
- CompletableFuture学习总结
CompletableFuture 简介 在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通 ...
- java调用webservice接口
1.直接AXIS调用远程的webservice 注意:不同版本的Axis相差很大,大家最好以apache网站上的例子为准,这里仅仅用于说明其基本用法. import org.apache.axis.c ...
- 预见预判_AIRIOT智慧交通管理解决方案
随着机动车保有量的逐步增加,城市交通压力日益增大.同时,新能源车辆的快速发展虽然带来了环保效益,但也因不限号政策而进一步加剧了道路拥堵问题.此外,各类赛事和重大活动的交通管制措施也时常导致交通状况复杂 ...
- objectarx 之让用户自定义插件命令
#include <iostream> #include <fstream> virtual AcRx::AppRetCode On_kInitAppMsg (void *pk ...
- 源码分析——MyBatis核心接口SqlSession的实现原理
在上一篇文章中(<MyBatis动态代理调用过程源码分析>),我们知道了MyBatis动态代理的核心是MapperProxy,在它内部封装了动态代理的调用逻辑,而我们也知道了在使用动态代理 ...
- 简单粗暴通过 Binlog 日志来恢复 MySQL 数据
引言 Binlog 日志的主要作用: 1.增量备份. 2.主从复制. 操作步骤 1.登录 MySQL -> 执行 show variables like '%log_bin%'; 查询 binl ...
- golang beego 使用supervisor 部署后台进程管理. 静态文件找不到的解决办法.
directory=/root/go/src/you_self_dir 请在客户端配置文件*.ini中加入一行命令, 等于号后面就是自己的项目目录,这时就能找到项目文件了.
- C# fastreport 实现各个报表指定各自的默认打印机
1.业务需求 工作室有多个报表需要打印,如果在报表模板里设置默认打印机的话,每个人电脑上安装的打印机是不相同的,所以就需要设定各自的默认打印机实现打印功能. 2.xml模板设计(PrinterSett ...
- pandas基础--缺失数据处理
pandas含有是数据分析工作变得更快更简单的高级数据结构和操作工具,是基于numpy构建的. 本章节的代码引入pandas约定为:import pandas as pd,另外import numpy ...
- java.sql.SQLException: MONTH 报错解决方法
idea控制台报错:java.sql.SQLException: MONTH Error attempting to get column 'xxx' from result set. Cause: ...