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) ...
随机推荐
- vben集成keycloak
前言 公司的项目是vben admin框架需要集成keycloak,那keycloak大家应该都不陌生了,就是统一认证的一个系统简称IDS.之前用过cas,并重构过cas的前端界面,所以对此也是比较熟 ...
- vue特殊atribute-is
1.解决dom内模板限制 有些 HTML 元素,诸如 <ul>.<ol>.<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制 ...
- IceRPC之服务器地址与TLS的安全性->快乐的RPC
作者引言 很高兴啊,我们来到了IceRPC之服务器地址与TLS的安全性->快乐的RPC, 基础引导,让自已不在迷茫,快乐的畅游世界. 服务器地址 ServerAddress 了解服务器地址的概念 ...
- 用 C 语言开发一门编程语言 — 交互式解释器
目录 文章目录 目录 前言 环境 编译型 vs 解释型 实现交互式解释器 使用 GNU Readline 函数库 前言 通过开发一门类 Lisp 的编程语言来理解编程语言的设计思想,本实践来自著名的& ...
- 因为我的一次疏忽而带来的golang1.23新特性
距离golang 1.23发布还有两个月不到,按照惯例很快要进入1.23的功能冻结期了.在冻结期间不会再添加新功能,已经添加的功能不出大的意外一般也不会被移除.这正好可以让我们提前尝鲜这些即将到来的新 ...
- pageoffice6提取word指定位置(数据区域)的值
在实际的开发过程中,经常会遇到提取Word文档中指定位置的数据保存到数据库中的需求,PageOffice客户端控件即支持在线保存Word文件,也支持Word文档中的指定位置的数据或所有的数据提交到服务 ...
- CMD程序_WordCount_博客改
程序简介 这个程序只能以命令行的方式启动,在启动时要输入相应的命令.程序的功能是对文本文件的字符数,单词数,行数进行统计,将结果输出到默认文件或指定文件. 码云项目链接:WordCount 程序结构 ...
- springboot 整合 recketMQ 详细步骤
前提 RocketMQ的部署环境可用 1 依赖包 <dependency> <groupId>org.apache.rocketmq</groupId> <a ...
- winform 绘图控件 chart 实时曲线图
官方教程:http:////files.cnblogs.com/files/HelloQLQ/Winform图表.rar 更多参考:https://blog.csdn.net/boxuming/art ...
- docker 容器镜像加速配置
登录阿里云容器镜像服务即可看到配置加速.