Java Apache Jexl规则引擎初体验

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、模板引擎的选择?
  • 二、什么是JEXL规则引擎?
          • 优点
          • 缺点
  • 三、其他规则引擎
  • 四、示例
    • 1.引入依赖
    • 2.方法示例
    • 3、代码解释
    • 4、效果
    • ![import java.util.*;](https://img-blog.csdnimg.cn/direct/560fb9361ba14b6ab72d42d2f49922ae.png)
  • 总结


前言

最近产品提了一个需求,通过前端页面点击生成表达式。来,请看大屏幕。。。错了,请看需求原型
在这里插入图片描述
通过前端按钮点击生成在公式展示栏的表达式,这里先不计较公式正确与否,就默认生成的公式一定是正确的,而生成的公式会作为传参传递到后端接口。


一、模板引擎的选择?

这里的公式仅用于匹配通过接口传入的类或者参数是否匹配,所以,这里不需要引入过重的表达式引擎,最终选择了Apache Jexl规则引擎

二、什么是JEXL规则引擎?

Apache Jexl(以下简称Jexl)是一种基于Java的表达式语言,用于在Java应用程序中计算和操作值。它可以用作规则引擎的一部分,但不是专门为此而设计的。与其他专为规则引擎而设计的引擎相比,Jexl具有以下优点和缺点。

优点
  • 易于学习和使用:Jexl的语法简单直观,易于理解和使用。它的API也很容易上手,对于新手来说非常友好。
  • 灵活性高:Jexl具有很高的灵活性,允许用户自定义函数、变量和操作符等,以满足各种需求。
  • 与Java集成良好:Jexl是基于Java的,因此可以非常方便地与Java应用程序集成。它可以轻松地与Java对象交互,并使用Java的反射机制来访问类和方法。
缺点
  • 不是专为规则引擎设计:尽管可以将Jexl用作规则引擎的一部分,但它并不是专为此而设计的。因此,在处理复杂的业务规则时,可能会存在一些限制和不足。
  • 缺少规则管理功能:Jexl本身只提供了表达式解析和计算功能,如果需要更复杂的规则管理功能,例如规则编辑、版本控制和审批流程等,需要自行实现或使用其他规则引擎。
  • 性能较差:由于Jexl是解释型语言,因此它的性能相对较低。如果需要处理大量数据或高并发场景,则可能需要考虑使用其他规则引擎。

三、其他规则引擎

市面上除了Jexl之外,还有许多其他的规则引擎可供选择,这里简单介绍一些在市面上比较常见的规则引擎:

  1. Drools:Drools 是一个开源规则引擎,它允许开发人员将业务逻辑与应用程序代码分离。它使用基于规则的语言(DRL)来表示和执行规则,并提供从多个数据源中自动推断输出结果的能力。

  2. Jess:Jess 是另一个基于规则的编程语言,它被设计为与 Java 集成。它可以用于构建专家系统、商业决策支持系统等。Jess 还包括一些高级特性,例如模式匹配和对象操作。

  3. Easy Rules:Easy Rules 是一个轻量级的规则引擎框架,它允许开发人员在应用程序中定义和执行简单的规则。它支持注解和 Lambda 表达式,并提供了与 Spring 和 CDI 的集成。

  4. Apache Spark MLlib:Apache Spark MLlib 是一个大规模机器学习库,它包含了许多算法和工具用于分类、回归、聚类和协同过滤等任务。它还提供了一组规则引擎,用于处理流数据和批数据。

  5. NRules:NRules 是一个 .NET 规则引擎,它允许开发人员定义和执行规则。它使用 C# 语言编写,并提供了与 LINQ 的集成,使得开发人员可以使用类似 SQL 的查询来过滤数据

四、示例

1.引入依赖

在 pom.xml 文件中添加以下依赖项:

	<dependency><groupId>org.apache.commons</groupId><artifactId>commons-jexl3</artifactId><version>3.2</version></dependency>

2.方法示例

代码如下(示例):

import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.MapContext;import java.util.*;public static void main(String[] args) {// 中文表达式String expStr = "(长<=120 且 宽<=60 且 高<=60 且 围长<=300 且 容积>150 且 重量<=31.5)" +" 或 (长>=121 且 长<=175 且 宽<=60 且 高<=60 且 围长<=300 且 容积<=150 且 重量<=31.5)" +" 或 (长<=120 且 宽>70 且 高<=60 且 围长<=300 且 容积<=150 且 重量<=31.5)";// Step 1:将中文且、或替换成java中的&&、||String replaceAfterStr = expStr.replaceAll("且", "&&").replaceAll("或", "||").replaceAll("围长", "perimeter").replaceAll("容积", "volume").replaceAll("重量", "weight").replaceAll("长", "length").replaceAll("宽", "width").replaceAll("高", "height");System.out.println("将中文且、或替换后的表达式:\n" + replaceAfterStr);// Step 2: 按照特定格式切割替换后表达式:"||"String[] split = replaceAfterStr.split("\\|\\|");List<String> splitExpStr = Arrays.asList(split);System.out.println("切割后的表达式:\n" + String.join("\n", splitExpStr));// Step 3:校验表达式是否符合JexlEngine engine = new JexlEngine();JexlContext context = new MapContext();context.set("length", 119);context.set("width", 59);context.set("height", 59);context.set("perimeter", 299);context.set("volume", 151);context.set("weight", 31.5);for (String s : splitExpStr) {Object evaluate = engine.getEngine().createExpression(s).evaluate(context);if (Boolean.FALSE.equals(evaluate)) {System.out.println("context不符合当前表达式:" + s);} else {System.out.println("context符合当前表达式:" + s);}}}

3、代码解释

这个方法的功能是通过解析和校验一个给定的中文表达式,来判断某些商品是否符合特定条件。具体步骤如下:

  1. 将中文的“且”和“或”替换为Java中的“&&”和“||”,并将其他中文关键词替换为对应的英文关键词。
  2. 将替换后的表达式按照“||”进行分割,得到多个子表达式。
  3. 创建一个JexlEngine对象用于解析表达式,并创建一个JexlContext对象用于设置待校验的上下文信息(长度、宽度、高度、围长、容积、重量)。
  4. 遍历分割后的子表达式,使用JexlEngine对每个子表达式进行求值,并根据求值结果判断上下文是否符合该子表达式。
  5. 最终输出符合或不符合子表达式的上下文信息。

4、效果

这个是运行结果

import java.util.*;

总结

这里说个问题,JEXL对于单表达式(例如:长<=120)组成的组合表达式是可以解析的,但是,如果你的单表达式写成(例:121<=长<=175)组成的组合表达式,Jexl是没办法解析的,所以,这种单表达式(例:121<=长<=175)你需要转换成(长>=121 且 长<=175),这样Jexl就会解析没问题

表达式:21<=长<=175解析报错信息

将中文且、或替换后的表达式:
(length<=120 && width<=60 && height<=60 && perimeter<=300 && volume>150 && weight<=31.5) || (121<=length<=175 && width<=60 && height<=60 && perimeter<=300 && volume<=150 && weight<=31.5) || (length<=120 && width>70 && height<=60 && perimeter<=300 && volume<=150 && weight<=31.5)
切割后的表达式:
(length<=120 && width<=60 && height<=60 && perimeter<=300 && volume>150 && weight<=31.5) (121<=length<=175 && width<=60 && height<=60 && perimeter<=300 && volume<=150 && weight<=31.5) (length<=120 && width>70 && height<=60 && perimeter<=300 && volume<=150 && weight<=31.5)
context符合当前表达式:(length<=120 && width<=60 && height<=60 && perimeter<=300 && volume>150 && weight<=31.5) 
Exception in thread "main" org.apache.commons.jexl3.JexlException$Parsing: com.smallrig.logistics.service.impl.LogisticsFreightOverrunRuleServiceImpl.main:257@1:13 parsing error in '<='at org.apache.commons.jexl3.JexlEngine.createExpression(JexlEngine.java:335)at com.smallrig.logistics.service.impl.LogisticsFreightOverrunRuleServiceImpl.main(LogisticsFreightOverrunRuleServiceImpl.java:257)

原创不易,望一键三连 (^ _ ^)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/14386.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++数据结构——哈希表

前言&#xff1a;本篇文章将继续进行C数据结构的讲解——哈希表。 目录 一.哈希表概念 二.哈希函数 1.除留取余法 三.哈希冲突 1.闭散列 线性探测 &#xff08;1&#xff09;插入 &#xff08;2&#xff09;删除 2. 开散列 开散列概念 四.闭散列哈希表 1.基本框架 …

场内期权怎么开户?佣金手续费最低是多少?

今天期权懂带你了解场内期权怎么开户&#xff1f;佣金手续费最低是多少&#xff1f;我国的首个场内期权是50ETF期权&#xff0c;随着投资者对期权产品日渐熟悉&#xff0c;投资者参与数量与交易量稳步增长。 场内期权怎么开户&#xff1f; 满足资金要求&#xff1a;根据监管要…

MyBatis:Parameter Maps collection does not contain value for 报错解决收录

MyBatis&#xff1a;Parameter Maps collection does not contain value for 报错问题解决收录 1.报错收录 后端测试时偶然遇到的用mybatis生成好的mapper文件&#xff0c;报Result Maps collection does not contain value…的错误 2.报错分析 java.lang.ILledalAraumentEx…

必应bing国内广告开户首充和开户费是多少?

微软必应Bing作为国内领先的搜索引擎之一&#xff0c;其广告平台凭借其精准的投放、高效的数据分析和广泛的用户覆盖&#xff0c;已成为众多企业的首选。 根据最新政策&#xff0c;2024年必应Bing国内广告开户预充值金额设定为1万元人民币起。这一调整旨在确保广告主在账户初始…

论文阅读--GLIP

把detection和phrase ground(对于给定的sentence&#xff0c;要定位其中提到的全部物体)这两个任务合起来变成统一框架&#xff0c;从而扩展数据来源&#xff0c;因为文本图像对的数据还是很好收集的 目标检测的loss是分类loss定位loss&#xff0c;它与phrase ground的定位los…

爬虫学习--11.MySQL数据库的基本操作(上)

MySQL数据库的基本操作 创建数据库 我们可以在登陆 MySQL 服务后&#xff0c;使用命令创建数据库&#xff0c;语法如下: CREATE DATABASE 数据库名; 显示所有的数据库 show databases; 删除数据库 使用普通用户登陆 MySQL 服务器&#xff0c;你可能需要特定的权限来创建或者删…

内脏油脂是什么?如何减掉?

真想减的人&#xff0c;减胖是很容易的&#xff0c;但想要形体美又健康&#xff0c;还是得从减内脏油脂开始&#xff0c;那么&#xff0c;问题来了&#xff0c;什么是内脏油脂&#xff1f; 油脂它分部于身体的各个角落&#xff0c;四肢、腹部、腰、臀部、脸、脖子...等&#xf…

VUE3+TS+elementplus创建table,纯前端的table

一、前言 开始学习前端&#xff0c;直接从VUE3开始&#xff0c;从简单的创建表格开始。因为自己不是专业的程序员&#xff0c;编程主要是为了辅助自己的工作&#xff0c;提高工作效率&#xff0c;VUE的基础知识并不牢固&#xff0c;主要是为了快速上手&#xff0c;能够做出一些…

Kubernetes中 Requests 和 Limits 的初步理解

1 灵魂拷问 我们在使用 Kubernetes 时是否遇到以下情况&#xff1a; 你会不会部署负载的时候将 CPU requests/limits 设置得过低或过高&#xff1f;你会不会部署负载的时候将 内存 requests/limits 设置得过低或过高&#xff1f;又或者你根本不设置 requests/limits&#xff…

SVN创建项目分支

目录 背景调整目录结构常规目录结构当前现状目标 调整SVN目录调整目录结构创建项目分支 效果展示 背景 当前自己本地做项目的时候发现对SVN创建项目不规范&#xff0c;没有什么目录结构&#xff0c;趁着创建目录分支的契机&#xff0c;顺便调整下SVN服务器上的目录结构 调整目…

【Vue】Vue2使用ElementUI

目录 Element UI介绍特点Vue2使用Element安装引入ElementUI组件库 使用ElementUI用户注册列表展示其他 mint-ui介绍特点安装组件引入组件Mint-ui相关组件 Element UI 介绍 官网(基于 Vue 2.x ):https://element.eleme.cn/#/zh-CN ElementUI 是一个基于 Vue.js 的桌面端组件库…

Vue文本溢出如何自动换行

css新增 word-break: break-all; word-wrap: break-word;

【Linux系统】文件与基础IO

本篇博客整理了文件与文件系统、文件与IO的相关知识&#xff0c;借由库函数、系统调用、硬件之间的交互、操作系统管理文件的手段等&#xff0c;旨在让读者更深刻地理解“Linux下一切皆文件”。 【Tips】文件的基本认识 文件 内容 属性。文件在创建时就有基本属性&#xff0…

网易:一季度营收269亿元,连续7季研发强度超15%领跑行业

5月23日&#xff0c;网易发布2024年第一季度财报。财报显示&#xff0c;网易Q1营收269亿元&#xff0c;归属于公司股东的净利润85亿元&#xff08;Non-GAAP&#xff09;&#xff0c;以连续7个季度超15%的研发投入强度领跑行业&#xff0c;首季业绩稳健启航。 一季度&#xff0…

JVM学习-动态链接和方法返回地址

动态链接–指向运行时常量池的方法引用 每一个栈帧内部包含一个指向运行时常量池中该栈帧所属方法的引用&#xff0c;包含这个引用的目的为了支持当前方法的代码能够实现动态链接(Dynamic Linking)&#xff0c;如invokednamic指令。在Java源文件被编译到字节码文件中时&#x…

JAVA:浅谈JSON与JSON转换

可能有很多人&#xff0c;无论是前端还是后端&#xff0c;无论是JAVA还是Python还是C&#xff0c;都应该跟JSON这种数据格式打过交道&#xff0c;那么有没有仔细的想过&#xff0c;什么叫JSON&#xff1f; JSON是一种轻量级的数据交换格式。它基于JavaScript语言的对象表示法&a…

初识java——javaSE(6)抽象类与接口【求个关注!】

文章目录 前言一 抽象类1.1 抽象类的概念1.2 抽象类的语法&#xff1a;1.3 抽象类与普通类的区别&#xff1a; 二 接口2.1 接口的概念2.2 接口的语法2.2.1 接口的各个组成2.2.2 接口之间的继承 2.3 接口的实现接口不可以实例化对象 2.4 接口实现多态 三 Object类3.1 Object类是…

第17讲:C语言内存函数

目录 1.memcpy使用和模拟实现2.memmove使用和模拟实现3.memset函数的使用4.memcmp函数的使用 1.memcpy使用和模拟实现 void * memcpy (void * destination, const void * source, size_t num);• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存…

网络安全技术与应用:远程控制与数据库安全

实验准备 软件&#xff1a;VMware Workstation Pro 虚拟机&#xff1a;Red Hat Enterprise Linux 7 服务器&#xff0c;Red Hat Enterprise Linux 7 客户端 网络模式&#xff1a;NAT模式 1、配置服务器及客户端网络 服务器IP 客户端IP 测试相互通信 在客户机上设置镜像&#…

车载网络测试实操源码_使用CAPL脚本模拟发送符合协议要求(Counter和CRC)的CAN报文

系列文章目录 车载网络测试实操源码_使用CAPL脚本解析hex、S19、vbf文件 车载网络测试实操源码_使用CAPL脚本对CAN报文的Counter和CRC进行实时监控 车载网络测试实操源码_使用CAPL脚本模拟发送符合协议要求(Counter和CRC)的CAN报文 车载网络测试实操源码_使用CAPL脚本实现安全…