Java Apache Jexl规则引擎初体验

news2024/11/19 5:56:30

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

文章目录

  • 前言
  • 一、模板引擎的选择?
  • 二、什么是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.coloradmin.cn/o/1715973.html

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

相关文章

ssm校园疫情防控管理系统-计算机毕业设计源码30796

目 录 摘要 1 绪论 1.1目的及意义 1.2开发现状 1.3ssm框架介绍 1.3论文结构与章节安排 2 校园疫情防控管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分…

Linux终端连接工具

终端连接工具有很多中&#xff0c;这里我只收集了一些常用的或免费的工具 我一般会配套使用&#xff1a; FinalShell -->命令行工具&#xff08;Mac和win&#xff09; WinSCP -->文件上传工具&#xff08;win&#xff09; filezilla -->文件上传工具&#xff08;Mac …

【408真题】2009-25

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…

Jetpack架构组件_5.BindingAdapter

1.BindingAdapter介绍 Binding adapters 可以作为一个设置某个值的框架来使用&#xff0c;databinding 库可以允许指定具体的方法来进行相关值的设置&#xff0c;在该方法中可以做一些处理逻辑&#xff0c;Binding adapters 会最终给你想要的结果。Android Databinding框架中已…

企业如何打造通证经济生态闭环详解(下)

一、原始账户&#xff1a;用户注册即生成【原始账户】【托管账户】。 原始账户用于存储用户所获取的通证积分&#xff0c;原始账户的公钥与私钥由用户所有&#xff0c;安全、私密、去中心化。 通过原始账户&#xff0c;用户可进行转账、收款的点对点传输&#xff0c;并可查看…

Activity详解,用最通俗的语言告诉你什么是Activity(一)

大家好&#xff0c;我是小布丁。 今天还是分享Android基础知识&#xff0c;有Android基础的朋友都知道&#xff0c;Activity作为Android四大组件之一&#xff0c;掌管可视化界面。也是大多数人刚接触Android学的第一课。下面我来带大家学习/复习这部分知识&#xff0c;请大家不…

Docker教程——Docker安装

安装 在安装Docker之前&#xff0c;我们需要执行如下代码安装Docker的一些依赖包&#xff0c; sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo依赖包安装好后&#xff0c;执行如下代码安装Dock…

Three.js是基于原生WebGL封装的三维引擎

Three.js: 基于原生WebGL封装的三维引擎 引言 随着互联网技术的发展&#xff0c;Web前端技术不断进步&#xff0c;用户对于网页交互体验的要求也越来越高。艾斯视觉前端开发&#xff1a;三维技术作为提升用户体验的重要手段之一&#xff0c;正在逐渐成为前端开发中的热门技术…

aws 在ecs外部实例上运行gpu负载

参考资料 https://docs.amazonaws.cn/zh_cn/AmazonECS/latest/developerguide/ecs-gpu.htmlhttps://docs.amazonaws.cn/AWSEC2/latest/UserGuide/accelerated-computing-instances.html#gpu-instanceshttps://docs.amazonaws.cn/AWSEC2/latest/UserGuide/install-nvidia-drive…

pytorch学习day1

一.pytorch主要模块介绍 1.1 模块介绍 模块描述torch包含激活函数和主要的张量操作torch.Tensor定义了张量的数据类型&#xff0c;方法可返回新张量&#xff0c;方法后缀带下划线可修改张量本身torch.cuda定义了 CUDA 运算相关的函数&#xff0c;如检查 CUDA 是否可用&#x…

FL Studio21.2.5中文版电子音乐制作的强大工具

在当今的数字音乐时代&#xff0c;电子音乐已经成为了全球音乐市场中不可或缺的一部分。越来越多的音乐爱好者开始尝试自己动手创作电子音乐&#xff0c;而FL Studio 21中文版正是为他们量身打造的一款强大工具。作为一个音频制作爱好者&#xff0c;我深知一个好的数字音频工作…

使用OrangePi KunPeng Pro部署AI模型

目录 一、OrangePi Kunpeng Pro简介二、环境搭建三、模型运行环境搭建(1)下载Ollama用于启动并运行大型语言模型(2)配置ollama系统服务(3)启动ollama服务(4)启动ollama(5)查看ollama运行状态四、模型部署(1)部署1.8b的qwen(2)部署2b的gemma(3)部署3.8的phi3(4)部署4b的qwen(5)部…

【问题解决】pycharm中添加python interpreter报错 conda excutable is no found

选择安装目录下的conda.bat文件&#xff0c;然后点击“Load Environments”按钮&#xff0c;然后在列表中选择conda环境即可。

工控一体机5寸显示器电容触摸屏(YA05WK)产品规格说明书

如果您对工控一体机有任何疑问或需求&#xff0c;或者对如何集成工控一体机到您的业务感兴趣&#xff0c;可移步控芯捷科技。 一、硬件功能介绍 YA05WK是我公司推出的一款新型安卓屏&#xff0c;4核Cortex-A7 架构&#xff0c;主频1.2GHz的CPU。采用12V供电&#xff0c;标配5寸…

MyBatis出现:SQLSyntaxErrorException: Unknown column ‘XXX‘ in ‘field list‘

<update id"updateStudent">update tb_students set stu_name${stuName},stu_gender${stuGender},stu_age${stuAge},stu_tel${stuTel}where stu_num ${stuNum}</update> 本质上来说&#xff0c;是Mybatis使用上的错误&#xff0c;不熟悉&#xff0c;理…

Swift 下标

下标 一、下标语法二、下标用法三、下标选项四、类型下标 下标可以定义在类、结构体和枚举中&#xff0c;是访问集合、列表或序列中元素的快捷方式。可以使用下标的索引&#xff0c;设置和获取值&#xff0c;而不需要再调用对应的存取方法。举例来说&#xff0c;用下标访问一个…

TC3xx分析--如何提高系统运行效率(2)

目录 1.概述 2.限定符对于代码的影响 3.小结 1.概述 上文TC3xx分析--如何提高系统运行效率(1)-CSDN博客讲解了Tasking中lsl的某些关键定义&#xff0c;简述了Tricore寻址模式&#xff0c;接下来我们继续看&#xff0c;不同memory限定符对于代码的影响。 2.限定符对于代码的…

工控一体机7寸显示器电容触摸屏(YR07JK)产品规格说明书

如果您对工控一体机有任何疑问或需求&#xff0c;或者对如何集成工控一体机到您的业务感兴趣&#xff0c;可移步控芯捷科技。 一、硬件功能介绍 1.1 YR07JK介绍 YR07JK工控机是我公司推出的一款新型 Cortex-A17 架构&#xff0c;主频达1.8GHz、具有高性能低能耗的工业控制板卡…

<Transition> expects exactly one child element or component.

近日在vue中使用 Transition 标签是发生了如下报错&#xff1a; [plugin:vite:vue] expects exactly one child element or component. 原因&#xff1a; 仅支持单个元素或组件作为其插槽内容。如果内容是一个组件&#xff0c;这个组件必须仅有一个根元素。 原始代码&#xff1…

李廉洋:5.29黄金趋势向下,原油持续走高,美盘走势分析及策略。

黄金消息面分析&#xff1a;当前美国存在一个令人担忧且未被充分关注的问题&#xff1a;房地产行业低迷、高利率和抵押贷款利率、租金高涨以及美联储的紧缩政策构成了一个恶性循环。由于高房价和高抵押贷款利率&#xff0c;美国住房经济活动远低于两年前的水平。为了让该行业好…