RuleEngine规则引擎底层改造AviatorScript 之公式规则

news2024/12/27 11:41:28

前情提要,看上一个文章,具体要实现的效果就是
在这里插入图片描述
当然上来的问题就是前端的问题,这个框首先他们用的是富文本,富文本传到后台的结果是前端脚本,带着h5的标签,后面改成了这个,当时这个东西其实和后端关系不大,就是如何处理换行符而已,使用这个之后换行符变成了/n
其实我们也是比着普通规则新建的一个功能,不过有很多的自己的设计
他们的实现是这样的

     */
    @Override
    public Object run(RunTestRequest runTestRequest) {
        log.info("模拟运行规则:{}", runTestRequest.getCode());
        RuleEngineGeneralRulePublish rulePublish = this.ruleEngineGeneralRulePublishManager.lambdaQuery()
                .eq(RuleEngineGeneralRulePublish::getStatus, runTestRequest.getStatus())
                .eq(RuleEngineGeneralRulePublish::getGeneralRuleCode, runTestRequest.getCode())
                .eq(RuleEngineGeneralRulePublish::getWorkspaceCode, runTestRequest.getWorkspaceCode())
                .one();
        if (rulePublish == null) {
            // 如果测试找不到,用线上  此场景出现在只有一个线上的时候
            rulePublish = this.ruleEngineGeneralRulePublishManager.lambdaQuery()
                    .eq(RuleEngineGeneralRulePublish::getStatus, DataStatus.PRD.getStatus())
                    .eq(RuleEngineGeneralRulePublish::getGeneralRuleCode, runTestRequest.getCode())
                    .eq(RuleEngineGeneralRulePublish::getWorkspaceCode, runTestRequest.getWorkspaceCode())
                    .one();
            if (rulePublish == null) {
                throw new ValidException("找不到可运行的规则数据:{},{},{}", runTestRequest.getWorkspaceCode(), runTestRequest.getCode(), runTestRequest.getStatus());
            }
        }
        Input input = new DefaultInput(runTestRequest.getParam());
        log.info("初始化规则引擎");
        RuleEngineConfiguration ruleEngineConfiguration = new RuleEngineConfiguration();
        Container.Body<GeneralRule> generalRuleContainer = ruleEngineConfiguration.getGeneralRuleContainer();
        GeneralRule rule = GeneralRule.buildRule(rulePublish.getData());
        generalRuleContainer.add(rule);
        GeneralRuleEngine engine = new GeneralRuleEngine(ruleEngineConfiguration);
        // 加载变量
        engine.getConfiguration().setEngineVariable(this.ruleEngineConfiguration.getEngineVariable());
        return engine.execute(input, runTestRequest.getWorkspaceCode(), runTestRequest.getCode());
    }

然后我们改成了这个样子

    @Override
    public Object formularun(RunTestRequest runTestRequest) {
        QueryWrapper<RuleEngineFunction2> wrapper = new QueryWrapper<>();
        List<RuleEngineFunction2> list = ruleEngineFunction2Manager.list(wrapper);
        for (int i = 0; i < list.size(); i++) {
            RuleEngineFunction2 ruleEngineFunction2 = list.get(i);
            //获取设置对应的方法名
            String className = ruleEngineFunction2.getClassName();
            String functionName = ruleEngineFunction2.getFunctionName();
            if (applicationContext.containsBean(className)) {
                AviatorFunction abstractFunction = (AviatorFunction)applicationContext.getBean(className);
                AviatorEvaluator.addFunction(abstractFunction);
            }
        }

        String funcation = runTestRequest.getFuncation();
        funcation = removeHtmlTags(funcation);
        System.out.println(funcation);
        Expression compiledExp = AviatorEvaluator.compile(funcation);

        Map<String, Object> param = runTestRequest.getParam();

        String res = String.valueOf(compiledExp.execute(param));
        System.out.println(res);
        return null;
    }

    public  String removeHtmlTags(String input) {
        return input.replaceAll("<[^>]*>", "");
    }
}

实现方式,但是这个时候出现了问题,就是函数底层实现的时候出现了问题,然后我们将函数的实现修改了,这个代码就几乎没有什么变动了,这个时候有一个另外的需求。就是需要有一个函数nvlFunction,这个函数是用来干啥的呢,就是说处理入参的,出现了这个函数就是表示有入参,这个函数一共两个参数,第一个参数,是取自函数这个功能的字段,要求是函数功能的函数code值,用来表示入参,另一个参数就是当这个入参不输入的时候,将这个参数赋值给对应的函数。
听着不难,实现的话我也是觉得挺简单的

@Function
public class NvlFunction extends AbstractFunction {
    @Override
    public String getName() {
        return "nvlFunction";
    }

    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        String letter1 = FunctionUtils.getStringValue(arg1, env);
        String letter2 = FunctionUtils.getStringValue(arg2, env);
        System.out.println("letter1"+letter1);
        System.out.println("letter2"+letter2);
        return new AviatorString(letter2);
    }
}

初版,发现不大行,如果参数没有穿进去不大对,

@Function
public class NvlFunction extends AbstractFunction {
    @Override
    public String getName() {
        return "nvlFunction";
    }

    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        if (arg1 != null && !"".equals(arg1)) {
            return arg1;
        }
        return arg2;
    }
}

然后换成了这个,发现也是不大行,即使为空的话这个对象AviatorObject 也不会为null

@Function
public class NvlFunction extends AbstractFunction {
    @Override
    public String getName() {
        return "nvlFunction";
    }

    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        Object param1 = arg1.getValue(env);
        if (param1 == null || param1.toString().isEmpty()) {
            return arg2;
        } else {
            return arg1;
        }
    }
}

发现了只有这个value是null,当这个入参是空的时候,至此改造全部完成了,剩下的就是他原本框架的小bug的修改以及小功能的新增了。

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

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

相关文章

【Linux】TCP编程{socket/listen/accept/telnet/connect/send}

文章目录 1.TCP接口1.1socket文档 1.2listen拓&#xff1a;端口号8080 1.3accept拓&#xff1a;今天全局函数 1.4读写接口1.5telnet1.一个客户端2.两个客户端 1.6ulimit -a1.7常识回顾1.8connect1.9拓&#xff1a;客户端的ip和地址什么时候被分配&#xff1f;1.10拓&#xff1a…

【接口自动化】参数化替换

在做接口测试时&#xff0c;除了测单个接口&#xff0c;还需要进行业务链路间的接口测试 比如[注册-登陆]需要token鉴权的业务流 当我们用使用postman/jmeter等工具时&#xff0c;将注册接口的一些响应信息提取出来&#xff0c;放到登陆接口的请求中&#xff0c;来完成某个业务…

【Redis】Redis群集的三种模式(主从、哨兵、群集)

redis群集有三种模式&#xff0c;分别是主从同步/复制、哨兵模式、Cluster&#xff0c;下面会讲解一下三种模式的工作方式&#xff0c;以及如何搭建cluster群集 ●主从复制&#xff1a;主从复制是高可用Redis的基础&#xff0c;哨兵和集群都是在主从复制基础上实现高可用的。主…

Qt案例 通过调用Setupapi.h库实现对设备管理器中设备默认驱动的备份

参考腾讯电脑管家-软件市场中的驱动备份专家写的一个驱动备份软件案例&#xff0c;学习Setupapi.h库中的函数使用.通过Setupapi.h库读取设备管理器中安装的设备获取安装的驱动列表&#xff0c;通过bit7z库备份驱动目录下的所有文件. 目录导读 实现效果相关内容示例获取SP_DRVIN…

DevOps已死?2024年的DevOps将如何发展

随着我们进入2024年&#xff0c;DevOps也发生了变化。新兴的技术、变化的需求和发展的方法正在重新定义有效实施DevOps实践。 IDC预测显示&#xff0c;未来五年&#xff0c;支持DevOps实践的产品市场继续保持健康且快速增长&#xff0c;2022年-2027年的复合年增长率&#xff0…

数字人解决方案——Champ单个视频单张图像生成可控且一致的人体视频生成

概述 Champ是阿里巴巴集团、南京大学和复旦大学的研究团队共同提出了一种创新的人体动画生成技术&#xff0c;Champ能够在仅有一段原始视频和一张静态图片的情况下&#xff0c;激活图片中的人物&#xff0c;使其按照视频中的动作进行动态表现&#xff0c;极大地促进了虚拟主播…

Git-LFS 远程命令执行漏洞 CVE-2020-27955 漏洞复现

今天遇到了一个比较有意思的洞&#xff0c;复现一下下.......... 漏洞描述 Git LFS 是 Github 开发的一个 Git 的扩展&#xff0c;用于实现 Git 对大文件的支持 一些受影响的产品包括Git&#xff0c;GitHub CLI&#xff0c;GitHub Desktop&#xff0c;Visual Studio&#xff0…

C#开发常用的库使用-Ioc库Autofac的使用

介绍 Autofac 是一个适用于 .NET 的强大的 IoC&#xff08;控制反转&#xff09;容器。它管理类之间的依赖关系&#xff0c;使得随着应用程序规模和复杂性的增长&#xff0c;应用程序仍然易于修改。它允许您管理 .NET 应用程序中的组件依赖关系&#xff0c;并自动将依赖项解析…

数据库(mysql)-基本查询语句(DQL)

查询语句 这边查询是给予一定表格,这边先做个解释 教师表包括(name(姓名),gender(性别),salary(工资),title(职位),subject_id(课程的编号),comm(奖金)) 学生表包括(姓名(name),gender(性别),job(职位),生日(birth)) 模版 SELECT 字段名 FROM 查询表 WHERE 查询语句 或与非…

Linux|从 STDIN 读取 Awk 输入

简介 在之前关于 Awk 工具的系列文章中&#xff0c;主要探讨了如何从文件中读取数据。但如果你希望从标准输入&#xff08;STDIN&#xff09;中读取数据&#xff0c;又该如何操作呢&#xff1f; 在本文中&#xff0c;将介绍几个示例&#xff0c;展示如何使用 Awk 来过滤其他命令…

Go语言实战:掌握html/template包的高效开发技巧

Go语言实战&#xff1a;掌握html/template包的高效开发技巧 引言Go标准库html包概览html包的基本用途html/template包的核心功能开始使用html/template应用场景 安全的HTML内容处理防范XSS攻击使用示例内容安全策略&#xff08;CSP&#xff09;小结 操作HTML元素创建和解析HTML…

java数据结构与算法刷题-----LeetCode628. 三个数的最大乘积

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 排序选择线性搜索最值 排序 解题思路&#xff1a;时间复杂度O( …

简介有向无环图DAG

Sui创纪录的每秒交易量部分归功于数学构造&#xff0c;即有向无环图&#xff08;Directed Acyclic Graph&#xff0c;DAG&#xff09;&#xff0c;该构造通过以最高效的方式处理交易来加速网络交易&#xff0c;而不是按照先来先服务的线性进展。 区块链是设计用于确保数据完整…

APx500音频分析仪硬件简介

两通道模拟输出&#xff0c;两通道或以上的模拟输入接口 线性编码数字音频接口&#xff08;AES/EBU,TOSLINK,SPDIF&#xff09;Linear PCM 脉冲密度调制码流&#xff08;需要APx-PDM选件支持&#xff09; Bluetooth蓝牙音频码流&#xff08;需APx-BT选件支持&#xff09; 最…

基于Android的记单词App系统的设计与实现

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

js 求出对应年月的开始日期和结束日期

实现效果&#xff1a; 背景&#xff1a; element日期时间选择组件&#xff0c;通过时间选择年-月&#xff0c;求出对应年月的开始日期和结束日期。 核心代码&#xff1a; /*** 返回给定年份和月份的起始和结束日期。* 202403 -> 2024-03-01 2024-03-31* param {number} y…

11-新热文章-实时计算

热点文章-实时计算 1 今日内容 1.1 定时计算与实时计算 1.2 今日内容 kafkaStream 什么是流式计算 kafkaStream概述 kafkaStream入门案例 Springboot集成kafkaStream 实时计算 用户行为发送消息 kafkaStream聚合处理消息 更新文章行为数量 替换热点文章数据 2 实时…

Linux下解决Java输出文件,中文变问号和中文乱码问题

# 启用 zh_CN.UTF-8 字体 echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen # 生成并安装 locale 数据 locale-gen # 更新当前 shell 环境 source /etc/default/locale 相当于以下操作&#xff1a; # Debian sudo apt install locales sudo dpkg-reconfigur…

基于SSM+Jsp+Mysql的超市管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

【第二十四篇】使用Burpsuite实现反射、储存、DOM型XSS(靶场实战案例)

目录 反射性XSS储存型XSSDOM XSS反射性XSS 搜索1后,审查元素: 猜测<font>标签中没有进行XSS特殊字符转义,而在<font>标签内,可使用<script>标签: <script>alert(1)</script>储存型XSS 该模块对姓名、电子邮件、网站做过滤处理,但评论处…