介绍

JEXL的全称是Java表达式语言(Java Expression Language),简单的说,它可以配合我们的Java程序运算一些简单的表达式。

具体可以识别哪些表达式?

包含最基本的加减乘除、大于小于等于、与或非、按位与、按位或、按位异或、按位补码;

除此之外还可以调用Java程序中方法,比如要判断一个字符串是否包含某一个字符。

点击查看15个典型用法代码示例

引入依赖

<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的更多相关文章

  1. Java虚拟机执行引擎

    执行引擎 关于执行引擎相关的部分, 在之前的博文里 Java内存区域中已经有所提及. 回顾一下: 也只有几个概念, JVM方法调用和执行的基础数据结构是 栈帧, 是内存区域中 虚拟机栈中的栈元素, 每 ...

  2. jvm虚拟机---执行引擎子系统

    Java虚拟机只与Class文件相关联,它规定了Class文件应该具有的格式,而不论该文件是由什么语言编写并编译而来.所以,任何语言只要能够最终编译成符合Java虚拟机要求的Class文件,就可以运行 ...

  3. 表达式语言引擎:Apache Commons JEXL 2.1 发布

    http://www.linuxde.net/2011/12/4348.html Commons JEXL 2.1 发布了,该版本和 2.0.1 是二进制兼容的,但源码不兼容,因为新增了两个接口: o ...

  4. Java | 在 Java 中执行动态表达式语句: 前中后缀、Ognl、SpEL、Groovy、Jexl3

    在一些规则集或者工作流项目中,经常会遇到动态解析表达式并执行得出结果的功能. 规则引擎是一种嵌入在应用程序中的组件,它可以将业务规则从业务代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业 ...

  5. 《深入理解Java虚拟机》-----第8章 虚拟机字节码执行引擎——Java高级开发必须懂的

    概述 执行引擎是Java虚拟机最核心的组成部分之一.“虚拟机”是一个相对于“物理机”的概念 ,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而 ...

  6. Java 实现String语句的执行(Jexl)

    https://www.jianshu.com/p/1000719e49fa 1.maven 导入库 <dependency> <groupId>org.apache.comm ...

  7. Java虚拟机-字节码执行引擎

    概述 Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,成为各种虚拟机执行引擎的统一外观(Facade).不同的虚拟机引擎会包含两种执行模式,解释执行和编译执行. 运行时帧栈结构 栈帧(Sta ...

  8. Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx

    Atitit.java expression fsm 表达式词法分析引擎 v2 qaa.docx C:\0workspace\AtiPlatf_cms\src\com\attilax\fsm\Java ...

  9. 深入理解java虚拟机(5)---字节码执行引擎

    字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...

  10. 《深入理解Java虚拟机》学习笔记之字节码执行引擎

    Java虚拟机的执行引擎不管是解释执行还是编译执行,根据概念模型都具有统一的外观:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果. 运行时栈帧结构 栈帧(Stack Frame) ...

随机推荐

  1. C#/.NET/.NET Core优秀项目和框架2024年4月简报

    前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍.功能特点.使用方式以及部分功能截图 ...

  2. linux下安装来自github的package失败

    最近使用go来做web服务器,当然还是得使用框架,于是找了几个:beego.echo等,但是我在安装得时候总是出现这类报错 cannot find package "github.com/l ...

  3. vulnhub --> Web Machine: (N7)

    靶场下载地址 Web Machine: (N7) << 点我 开始打靶 ip发现: nmap扫描网段发现靶机ip:192.168.56.101 端口发现: 对靶机进行常规端口扫描 访问网站 ...

  4. 逆向WeChat(三)

    本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18198572 上篇回顾,对象是WEUIEngine.WeUIEngine使用了chrome::base框架,但只用 ...

  5. 谁说爬虫只能Python?看我用C#快速简单实现爬虫开发和演示!

    前言:说到爬虫,基本上清一色的都知道用Python,但是对于一些没玩过或者不想玩Python的来说,却比较头大一点.所以以下我站在C# 的角度,来写一个简单的Demo,用来演示C# 实现的简单小爬虫. ...

  6. 利用instruments工具查看其它app的性能

    1.随便建立一个新的工程文件,profile,进入instruments 2.选中activity,可以看到所有进程,以及其它进程的CPU占用情况

  7. bashrc和profile区别

    转载请注明出处: 作用与目的: .bashrc:这个文件主要用于配置和自定义用户的终端环境和行为.每次启动新的终端时,.bashrc文件都会被执行,加载用户设置的环境变量.别名.函数等.这使得用户能够 ...

  8. 【深度学习】c++部署onnx模型(Yolov5、PP-HumanSeg、GoogLeNet、UNet)

    这两天部署了好多模型,记录一下.代码链接. onnxruntime在第一张图的推理上比opencv快很多,但在后面的图上略微慢了一点. 不同的模型的部署时的输出不同,处理时需要对输出比较了解,下面分别 ...

  9. .NET 中使用 OpenTelemetry Traces 追踪应用程序

    上一次我们讲了 OpenTelemetry Logs.今天继续来说说 OpenTelemetry Traces. 在今天的微服务和云原生环境中,理解和监控系统的行为变得越来越重要.在当下我们实现一个功 ...

  10. mysql 常用脚本语法

    mysql 常用脚本语法 创建表: CREATE TABLE test_db1.test_table1 ( id INT auto_increment NOT NULL, my_name varcha ...