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) ...
随机推荐
- Js使用面向对象和面向过程的方法实现拖拽物体的效果
1.面向过程的拖拽实现代码: <!DOCTYPE html> <html> <head> <title>drag Div</title> & ...
- 简单聊一聊Java的历史
Java这门语言有很多不可忽视的优点,比如一次编写到处运行,又比如它有一个相对安全的内存管理和访问机制,避免了C++中经常出现的内存泄露和指针越界问题等等,java带来的这些好处,让我们这些java程 ...
- pageoffice6 版本实现在线打开word 文件禁止保存、禁止另存、禁止打印的需求
在实际项目需求中,有时需要限制用户的保存.另存.打印文件操作,实现此效果只需在OnPageOfficeCtrlInit或AfterDocumentOpened事件中调用js设置PageOffice控件 ...
- AIRIOT物联网低代码平台如何配置MQTT驱动?
MQTT驱动配置简介 MQTT全称为消息队列遥测传输(英语:Message Queuing Telemetry Transport),是ISO 标准(ISO/IEC PRF 20922)下基于发布 ( ...
- 使用Chrome 开发者工具提取对应的字符串
最近在查看一个API的数据,效果很好,但是里面只有一部分我想要的内容 如果是简单一点的可以直接获取 如下比如我想要提取返回的代码中关键的字符串:"video": "这里的 ...
- elementui table tree懒加载只能执行一次的解决办法
绑定 table的:key为随机值,在每次查询更新table时,更改key,就能刷新 table tree 懒加载只能第一次有效的问题, 本来那个懒加载只能执行一次,即使重新绑定了数据列表,再展开,也 ...
- Swoole 源码分析之 Coroutine 协程模块
首发原文链接:Swoole 源码分析之 Coroutine 协程模块 大家好,我是码农先森. 引言 协程又称轻量级线程,但与线程不同的是:协程是用户级线程,不需要操作系统参与.由用户显式控制,可以在需 ...
- 一款功能强大的Python工具,一键打包神器,一次编写、多平台运行!
1.项目介绍 Briefcase是一个功能强大的工具,主要用于将Python项目转化为多种平台的独立本地应用.它支持多种安装格式,使得Python项目能够轻松打包并部署到不同的操作系统和设备上,如ma ...
- SQL必知必会(第5版) 读书笔记
适用范围 本书涵盖的DBMS一般来说,本书中所讲授的SQL可以应用到任何数据库管理系统(DBMS).但是,各种SQL实现不尽相同,本书介绍的SQL主要适用于以下系统(需要时会给出特殊说明和注释): ❑ ...
- css做多列瀑布流
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...