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) ...
随机推荐
- IDEA连接github
在IDEA中添加github账号: File-->Settings-->Version Control-->GitHub 点击 + 号,添加账号可以选择账号密码登陆或者使用token ...
- Oracle中ALTER TABLE的五种用法(一)
首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...
- kettle使用1-全表导入
1.新建转换 2.DB连接中,新建数据库连接 3.在输入中,选择表输入 选择连接的数据库和查询的sql的数据 4.再输出中,选择表输出 5.按住shift,建立数据连接 6.匹配数据字段映射
- OpenTelemetry agent 对 Spring Boot 应用的影响:一次 SPI 失效的
背景 前段时间公司领导让我排查一个关于在 JDK21 环境中使用 Spring Boot 配合一个 JDK18 新增的一个 SPI(java.net.spi.InetAddressResolverPr ...
- 提升WordPress网站加载速度的8个小技巧
提升WordPress网站加载速度是至关重要的,它不仅可以提高用户体验,还有助于SEO排名.以下是提升WordPress网站加载速度的8个小技巧,希望能帮助到大家. 优化图片: 使用适当大小和格式的图 ...
- Python RabbitMQ Demo
fanout消息订阅模式 生产者 # 生产者代码 import pika credentials = pika.PlainCredentials('guest', 'guest') # mq用户名和密 ...
- 一文读懂Apollo客户端配置加载流程
SpringBoot集成Apollo源码分析 本文基于 apollo-client 2.1.0 版本源码进行分析 Apollo 是携程开源的配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修 ...
- vue-cli3 项目路由 history 模式部署到 nginx 服务器
1.项目修改vue.config.js增加 publicPath: '/' 2.nginx配置 location / {#访问前端页面 root /data/dist;#vue项目存放路径 index ...
- Centos安装Redis(极速安装)
下载 从官网找到下载文件,我下载的是redis-6.0.16.tar.gz. 安装 1. 解压文件 解压文件然后,进入解压文件夹: tar -zxvf redis-6.0.16.tar.gz cd r ...
- P7959 [COCI2014-2015#6] WTF 题解
P7959 [COCI2014-2015#6] WTF 题解 呃,是一道 DP 题 说实话,原题实际上是不要输出一种方法的--但是似乎放这道题的人想增加一点难度? 这里有两种做法,但都是 DP. 预备 ...