当前位置: 首页 > news >正文

规则引擎技术解决方案

1 概述

1.1 规则引擎的背景

业务系统在应用过程中,常常包含着要处理“复杂、多变”的部分,这部分往往是“业务规则”或者是“数据的处理逻辑”。因此这部分的动态规则的问题,往往需要可配置,并对系统性能和热部署有一定的要求。从开发与业务的视角主要突出以下的一些问题:

1.1.1从开发人员视角来看

1)逻辑复杂,要使用大量if-else、switch-case来实现,或者使用设计模式。 但过于复杂的规则逻辑,使用设计模式也往往是存在大量并且关系复杂 的类,导致代码难于维护。

2)变更时需要从头梳理逻辑,在适当的地方进行if…else…、switch-case代码 逻辑调整,耗费大量时间进行梳理。

3)开发周期较长,当需求发生变更时,需要研发人员安排开发周期上线, 对于当下快速变化的业务,传统的开发工作方式显得捉襟见肘。

1.1.2从业务人员视角来看

1)业务人员期望友好的管理界面,不需要专业的开发技能就能够完成规则 的管理、发布。

2)期望能够实现热部署,由业务人员配置好之后即配即用。

3)减少业务规则对开发人员的依赖。

4)降低需求变动的时间成本,快速验证发布。

1.2 规则引擎介绍

规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。

规则本质上是一个函数,如y=f(x1,x2,….xn)。

规则引擎有三部分:

  1. 事实(Fact):就是用户驶入的已经事实,即已知对象。
  2. LHS(Left Hand Side):规则执行需要满足的条件。
  3. RHS(Right Hand Sike):规则执行后的返回对象。

两个重要模块:

  1. 规则管理:主要涉及规则、实施对象和规则集三个实体。涉及到规则变更时,最好对规则加版本,可通过规则版本控制,可以平滑灰度地改变规则,也便于测试规则的正确性。
  2. 规则执行:通过规则库数据,通过规则引擎的规则解析、规则编译,将可执行代码缓存起来。也可根据需求,不依赖规则库的存储方式,如选用Drools等第三方引擎,甚至基于ANTLR定制。

1.3 规则引擎使用场景

◆ 使用规则引擎的好处

■ 声明式编程:规则引擎允许你描述做什么而不是如何去做

■ 业务规则与系统代码分离,实现业务规则的集中管理。数据保存在系统对象中,逻辑保存在规则中。

■ 速度及可测量性:Rete算法、Leaps算法,以及由此衍生出来的Drools的Rete、Leaps算法,提供了对系统数据对象非常有效率的匹配

■ 知识集中化:通过使用规则,将建立一个可执行的规则库。这意味着规则库代表着现实中的业务策略的唯一对应,理想情况下可读性高的规则还可以被当作文档使用

■ 工具集成:例如Eclipse(将来可能在基于Web的界面上)这样的工具为规则的修改与管理、即时获得反馈、内容验证与修补提供了办法。审查与调试工具同样也可用了

■ 解释机制:通过将规则引擎的决断与决断的原因一起记录下来,规则系统提供了很好的“解释机制”

■ 易懂的规则:通过建立对象模型以及DSL(域定义语言),可以用接近自然语言的方式来编写规则。规则引擎是相对独立的,只关心业务规则,使得业务分析⼈员、非技术人员与领域专家也可以用他们自己的逻辑来理解规则,参与编辑、维护系统的业务规则

   ■  在不重启服务的情况下可随时对业务规则进行扩展和维护

   ■ 可以动态修改业务规则,从⽽快速响应需求变更

   ■ 减少了硬编码业务规则的成本和风险

   ■ 使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单 

◆ 适合使用规则引擎系统的场景

  ■ 用传统的代码开发比较复杂、繁琐

■ 问题虽然不复杂,但是用传统的代码开发比较脆弱,也就是经常修改

■ 没有优雅的算法

■ 业务规则频繁改变

■ 有很多业务专家

如:

  • 风险控制系统----风险贷款、风险评估
  • 反欺诈项目----银行贷款、征信验证
  • 决策平台系统----财务计算
  • 促销平台系统----满减、打折、加价购
  • 手机运营商资费套餐
  • 超市、商场,商城等等积分计算规则
  • 寿险车险理赔
  • 工资计算(ScriptEngine)
  • 决策平台系统----业务决策判断
  •  PS:如果应用的生命周期很短,也没有必要使用Drools,使用规则引擎将会在中长期维护中得到好处。

◆ 不适合使用规则引擎系统的场景

虽然规则系统看起来比较不错,但是并不是任何地方都可以使用规则系统。

■ 很多简单、固定的业务系统,可以不用使用规则系统

■ 问题虽然不复杂,但是用传统的代码开发比较脆弱,也就是经常修改

■ 没有优雅的算法

■ 业务规则频繁改变

■ 开发时间紧、任务急、工作量大

2 总体设计方案

暂无。

3 规则引擎技术选型

对比内容DroolseasyRulesQlExpressApache Camel
项目背景JBoss                阿里Apache
SpringBoot整合 VV支持Spring支持Spring
平台支持JavaJavaJavaJava
热更新VXX/
维护一般/
LHS规则条件VVV/
RHSthen部分触发执行、业务处理VVV/
活跃度非常活跃的社区支持;star 4.6k/last update 2023.8.2/commits 16898star 4.5k/last update 2020.12.7/commits 659star 4.2k/last update 2023.2.6/commits 309star 4.9k/last update aways/commits 309
性能良好高性能/
学习成本引擎设计和实现都比较复杂,学习成本高,适用于大型应用系统方便且适用于Java的抽象的业务模型规则,轻量级类库和容易上手需要一定的学习成本需要一定的学习成本
免费开源VVVV
复杂业务场景的支持复杂规则支持简单规则。基于MVEL表达式的编程模型(适用于极简单的规则,一般不推荐)复杂规则支持/
技术成熟度一般一般
规则引擎类型业务规则引擎业务规则引擎业务规则引擎,表达式路由和中介规则引擎。适用于集成/传输层。在系统之间映射消息格式,转换协议(JMS,HTTP,FTP等)和消息标准(如XML,JSON等)以及路由

3.1目前业务特点选型

法律法规业务规则、表达式(布尔组合)、语义语法分析等强业务需求,由业务人员将历年法律法规规则按照规则编写xml文档,由后端读取XML规则内容,通过对法律案例进行分词、匹配、正则表达式、语义关联分析等与读取的XML规则内容比对、匹配,实现对法律案例的关键字的提取,从而获取相应的结果。根据实际情况,先采用硬编码读取XML文件进行对text内容比对、匹配等方式完成任务。后期通过分享Drools、easyRule的方式实现业务和技术的分离,争取考虑使用页面配置规则存库、读取规则、匹配规则方式,形成公司自有的规则库。

4.Drools简介及使用

Drools是⼀款由JBoss组织提供的基于Java语⾔开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在⽂件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、不⽤重启服务器就可以在线上环境立即生效。

 Drools官网地址:https://drools.org/

​ drools源码下载地址:https://github.com/kiegroup/drools

使用 Drools 需要将原有的代码抽象成:Rule(规则) + Fact(事实)。

在Java应用中使用Drools 规则引擎的步骤如下:

1.准备规则:创建规则文件并定义规则。

2.构建Kie容器:使用KieServices接口创建Kie容器。

3.获取KieBase:使用KieServices.newKieClasspathContainer()方法获取KieBase。

4.创建KieSession:使用KieBase.newKieSession)方法创建KieSession。

5.插入数据:使用KieSession.insert()方法插入数据。

6.执行规则:使用KieSession.fireAllRules()方法执行规则。

7.关闭KieSession:使用KieSession.dispose()方法关闭KieSession。

4.1 pom导包

<dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>7.57.0.Final</version>
</dependency>
<dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>7.57.0.Final</version>
</dependency>
<dependency><groupId>org.kie</groupId><artifactId>kie-api</artifactId><version>7.57.0.Final</version>
</dependency>
<dependency><groupId>org.drools</groupId><artifactId>drools-mvel</artifactId><version>7.57.0.Final</version>
</dependency>

Idea安装Drools插件。

4.2 resource下新建META-INF文件夹,新建并编写kmodule.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule"><!--name:指定kbase 名称,可以是任意但必须唯一packages:指定规则文件存放目录,依据实际情况进行填写default:指定当前的kbase 是否为默认--><kbase name="rules" packages="rules" default="true"><!--name:指定ksession名称,可以是任意但必须唯一default:指定ksession 是否为默认--><ksession name="ksession-rules" default="true"/><!--<ksession name="name-rules" default="true"/>--></kbase>
</kmodule>

4.3 resource下新建rules文件夹,新建并编写crime-rules.drl文件

package rules;import com.example.testdemo.Judge;rule "crime_1"
when$judge:Judge(crime.contains("猥亵"));
then$judge.setSentence(3);System.out.println("触发猥亵,3个月");
endrule "crime_2" extends "crime_1"
whenJudge(crime.contains("抢劫"));
then$judge.setSentence(24);System.out.println("触发猥亵和抢劫, 2年");
endrule "crime_3" extends "crime_2"
whenJudge(crime.contains("杀人未遂"));
then$judge.setSentence(120);System.out.println("触发猥亵、抢劫、杀人未遂, 10年");
end

4.4 编写测试用例

/*** @author jingyan* @createTime 2019年07月04日 13:51:00* @Description*/
public class TestDrools {@Testpublic void test1() {// 第一步KieServices kieServices = KieServices.Factory.get();// 第二步KieContainer kieContainer = kieServices.getKieClasspathContainer();// 第三步KieSession kieSession = kieContainer.newKieSession("ksession-rules");// 业务对象Judge judge = new Judge();judge.setCrime("嫌疑人xxx,于2012年因猥亵、抢劫、杀人未遂,数案并罚");// 第四步kieSession.insert(judge);// 第五步:执行规则引擎kieSession.fireAllRules();// 第六步:关闭sessionkieSession.dispose();System.out.println("指定规则引擎后的结果:" + judge.getSentence());}
}

运行结果:

14:52:07.483 [main] INFO org.drools.compiler.kie.builder.impl.KieContainerImpl - End creation of KieBase: rules
14:52:07.535 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
触发猥亵,3个月
触发猥亵和抢劫, 2年
触发猥亵、抢劫、杀人未遂, 10年
14:52:07.571 [main] DEBUG org.drools.core.common.DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
14:52:07.571 [main] DEBUG org.drools.core.common.DefaultAgenda - State was HALTING is now INACTIVE
14:52:07.571 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now DISPOSED
指定规则引擎后的结果:120

4.5Drools数据库表结构设计

-- ----------------------------
-- Table structure for drools_biz_rule
-- ----------------------------
DROP TABLE IF EXISTS `drools_biz_rule`;
CREATE TABLE `drools_biz_rule`  (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',`rule_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '规则标识',`rule_condition` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '规则数据',PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `uni_code`(`rule_code`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

5.EasyRule简介及使用

     easy-rules是一款轻量级的java规则引擎。支持快速简单的从yml、json文件中加载Rule描述文件。EasyRule是Drools的简化版,裁剪了部分使用场景非常少的复杂功能,也简化了很多Drools中的组件。

官网:https://github.com/j-easy/easy-rules/

5.1框架特点

  • 轻量级类库
  • 容易学习的API
  • 基于POJO的注解编程模型开发
  • 通过高效的抽象来定义业务规则并易于用JAVA应用它们
  • 支持通过原始规则创建复合规则
  • 支持用表达式语言定义规则

5.2功能组件

  • 事实(Fact):业务数据,结构类似HashMap;
  • 规则(Rule):业务规则,包含条件评估、动作执行,条件评估结果为true,则执行对应动作;
  • 规则引擎(Rule Engine):以指定的方式执行规则;
  • 规则监听(Rule Listener):监听规则的执行情况;
  • 规则引擎监听(Rule Engine Listener):监听规则引擎的执行情况。

5.3EasyRule使用

5.3.1 pom导包

<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-core</artifactId><version>4.1.0</version>
</dependency>
<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-support</artifactId><version>4.1.0</version>
</dependency>
<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-mvel</artifactId><version>4.1.0</version>
</dependency>

5.3.2 resource下新建easyrules文件夹,新建并编写rule.yml文件

---
name: "crime_1"
description: "猥亵罪"
#priority: 1
condition: "judge.crime.contains(\"猥亵\")"
actions:- "judge.setSentence(3)"- "System.out.println(\"触发猥亵,3个月\")"---
name: "crime_2"
description: "猥亵和抢劫罪并罚"
#priority: 2
condition: "judge.crime.contains(\"猥亵\")&&judge.crime.contains(\"抢劫\")"
actions:- "judge.setSentence(24)"- "System.out.println(\"触发猥亵和抢劫, 2年\")"---
name: "crime_3"
description: "猥亵、抢劫罪和杀人未遂并罚"
#priority: 0
condition: "judge.crime.contains(\"猥亵\")&&judge.crime.contains(\"抢劫\")&&judge.crime.contains(\"杀人未遂\")"
actions:- "judge.setSentence(120)"- "System.out.println(\"触发猥亵、抢劫、杀人未遂, 10年\")"

5.3.3.4 编写测试用例

/*** @author jingyan* @createTime 2019年07月04日 15:54:00* @Description*/
public class TestEasyRule {@Testpublic void test() throws Exception {// 创建规则引擎RulesEngineParameters parameters = new RulesEngineParameters()//优先级超过定义的阈值,则跳过下一个规则//.priorityThreshold(10)//规则被触发时跳过后面的规则.skipOnFirstAppliedRule(false)//规则失败时跳过后面的规则.skipOnFirstFailedRule(true)//一个规则不会被触发跳过后面的规则.skipOnFirstNonTriggeredRule(false);RulesEngine engine = new DefaultRulesEngine(parameters);// 创建规则String filePath = System.getProperty("user.dir") + "/src/main/resources/easyrules/rule.yml";MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());Rules yamlRules = ruleFactory.createRules(new FileReader(filePath));Judge judge = new Judge();judge.setCrime("嫌疑人xxx,于2012年因猥亵、抢劫、杀人未遂,数案并罚");// 执行规则Facts facts = new Facts();facts.put("judge", judge);engine.fire(yamlRules, facts);System.out.println("指定规则引擎后的结果:" + JSON.toJSONString(judge));}
}

运行结果:

17:12:28.204 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact{name='judge', value=Judge(crime=嫌疑人xxx,于2012年因猥亵、抢劫、杀人未遂,数案并罚, sentence=0)}
17:12:28.204 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
17:12:28.229 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'crime_1' triggered
触发猥亵,3个月
17:12:28.232 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'crime_1' performed successfully
17:12:28.233 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'crime_2' triggered
触发猥亵和抢劫, 2年
17:12:28.233 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'crime_2' performed successfully
17:12:28.234 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'crime_3' triggered
触发猥亵、抢劫、杀人未遂, 10年
17:12:28.234 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'crime_3' performed successfully
指定规则引擎后的结果:{"crime":"嫌疑人xxx,于2012年因猥亵、抢劫、杀人未遂,数案并罚","sentence":120}

5.3.3.5EasyRule数据库表结构设计

-- ----------------------------
-- Table structure for easy_biz_rule
-- ----------------------------
DROP TABLE IF EXISTS `easy_biz_rule`;
CREATE TABLE `easy_biz_rule` (`id` bigint(22) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '规则名称',`description` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规则描述',`priority` int(11) DEFAULT NULL COMMENT '权重',`composite_type` tinyint(4) DEFAULT NULL COMMENT '组合类型 1-and 2-or 3-all',`state` tinyint(4) DEFAULT NULL COMMENT '数据状态 0-有效 1-无效',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_name` (`name`) USING BTREE COMMENT '策略名称'
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;-- ----------------------------
-- Table structure for easy_biz_compose
-- ----------------------------
DROP TABLE IF EXISTS `easy_biz_compose`;
CREATE TABLE `easy_biz_compose` (`id` bigint(22) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',`rule_id` bigint(22) NOT NULL COMMENT '规则ID',`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规则名称',`description` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规则描述',`condition` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '规则条件',`actions` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '执行动作',`priority` int(11) DEFAULT NULL COMMENT '规则权重',`state` tinyint(4) DEFAULT NULL COMMENT '数据状态 0-有效 1-无效',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_rule` (`rule_id`) USING BTREE COMMENT '规则'
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;

6.QLExpress简介和使用

由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。让业务人员就可以定义业务规则。支持标准的JAVA语法,还可以支持自定义操作符号、操作符号重载、函数定义、宏定义、数据延迟加载等。

QLExpress脚本引擎被广泛应用在阿里的电商业务场景,具有以下的一些特性:

  • 1、线程安全,引擎运算过程中的产生的临时变量都是threadlocal类型。
  • 2、高效执行,比较耗时的脚本编译过程可以缓存在本地机器,运行时的临时变量创建采用了缓冲池的技术,和groovy性能相当。
  • 3、弱类型脚本语言,和groovy,javascript语法类似,虽然比强类型脚本语言要慢一些,但是使业务的灵活度大大增强。
  • 4、安全控制,可以通过设置相关运行参数,预防死循环、高危系统api调用等情况。
  • 5、代码精简,依赖最小,250k的jar包适合所有java的运行环境,在android系统的低端pos机也得到广泛运用。

官网:https://github.com/alibaba/QLExpress

6.1 pom导包

<dependency><groupId>com.alibaba</groupId><artifactId>QLExpress</artifactId><version>3.3.1</version>
</dependency>

6.2编写测试用例

/*** @author jingyan* @createTime 2023年08月04日 18:04:00* @Description 补充QLExpress表达式规则引擎*/
public class TestQLExpress {@Testpublic void test() throws Exception {ExpressRunner runner = new ExpressRunner();DefaultContext<String, Object> context = new DefaultContext<>();context.put("a", 1);context.put("b", 2);context.put("c", 3);String express = "a + b * c";Object r = runner.execute(express, context, null, true, false);System.out.println(r);runner.addOperatorWithAlias("如果", "if", null);runner.addOperatorWithAlias("则", "then", null);runner.addOperatorWithAlias("否则", "else", null);express = "如果 (语文 + 数学 + 英语 > 270) 则 {return 1;} 否则 {return 0;}";Object o = runner.execute(express, context, null, false, false, 50);System.out.println(o);/*runner.addFunctionOfClassMethod("取绝对值", Math.class.getName(), "abs", new String[] {"double"}, null);runner.addFunctionOfClassMethod("转换为大写", BeanExample.class.getName(), "upper", new String[] {"String"}, null);runner.addFunctionOfServiceMethod("打印", System.out, "println", new String[] { "String" }, null);runner.addFunctionOfServiceMethod("contains", new BeanExample(), "anyContains", new Class[] {String.class, String.class}, null);String express1 = "取绝对值(-100); 转换为大写(\"hello world\"); 打印(\"你好吗?\"); contains(\"helloworld\",\"aeiou\")";Object e = runner.execute(express1, context, null, false, false);System.out.println(e);*/}
}

运行结果:

Connected to the target VM, address: '127.0.0.1:11215', transport: 'socket'
7
1
Disconnected from the target VM, address: '127.0.0.1:11215', transport: 'socket'

6.3resource下新建qLrules文件夹,新建并编写rule.ql文件

是否符合 = 1;
运费 = 0;
最长边 = 长 > 宽 ? 长 : 宽;
最长边 = 最长边 > 高 ? 最长边 : 高;
最短边 = 长 < 宽 ? 长 : 宽;
最短边 = 最短边 < 高 ? 最短边 : 高;
中间边 = (长 + 宽 + 高) - 最长边 - 最短边;
围长 = (中间边 + 最短边) * 2 + 最长边;
如果 (围长 > 300) 则{是否符合 = 0;return 是否符合;
}
如果 (最长边 > 175) 则{是否符合 = 0;return 是否符合;
}
如果 (30 >= 重量 ) 则{是否符合 = 0;return 是否符合;
}
如果 (30 < 重量 ) 则{是否符合 = 0;运费 = 1.5*(重量-30);return 是否符合;
}

6.4编写测试用例

@Test
public void ruleTest() throws Exception {List<String> ruleFileNames = new ArrayList<>();ruleFileNames.add("qLrules/rule.ql");for (int i = 0; i < ruleFileNames.size(); i++) {String script = getResourceAsStream(ruleFileNames.get(i));ExpressRunner runner = new ExpressRunner(false, false);runner.addOperatorWithAlias("如果", "if", null);runner.addOperatorWithAlias("则", "then", null);runner.addOperatorWithAlias("否则", "else", null);IExpressContext<String, Object> context = new DefaultContext<>();try {context.put("长", 2);context.put("宽", 20);context.put("高", 40);context.put("重量", 35);context.put("COUNTRY","IS");runner.execute(script, context, null, true, false);System.out.println("文件名称:" + ruleFileNames.get(i));System.out.println("最长边:" + context.get("最长边"));System.out.println("中间边:" + context.get("中间边"));System.out.println("最短边:" + context.get("最短边"));System.out.println("是否符合:" + context.get("是否符合"));System.out.println("运费:" + context.get("运费"));} catch (Exception e) {e.printStackTrace();//Assert.assertTrue(e.toString().contains("at line 7"));}}
}

运行结果:

Connected to the target VM, address: '127.0.0.1:13783', transport: 'socket'
文件名称:qLrules/rule.ql
最长边:40
中间边:20
最短边:2
是否符合:0
运费:7.5
Disconnected from the target VM, address: '127.0.0.1:13783', transport: 'socket'

7.Apache Camel简介

Apache Camel是Apache基金会下的一个开源项目,它是一个基于规则路由和中介的规则引擎。包括基于Java的Fluent API,Spring或者Blueprint XML配置文件,甚至是Scala(是一种基于JVM,集合了面向对象编程和函数式编程优点的高级程序设计语言)DSL。 能够通过IDE或者Java、Scala或者XML编辑器里获得智能化路由规则补全功能。

Apache Camel可以做到:

路由:将数据有效负载(也称为“消息”)从源系统发送到目标系统。from().to().to()。

中介:消息处理,如基于一个或多个消息属性过滤消息、修改消息的某些字段、通过API调用进行充实等。

在面向服务的体系结构的项目中,Camel通常与Apache ServiceMix, Apache ActiveMQ以及Apache CXF一同使用。

◆ 适合使用Apache Camel的场景:

  • 具有丰富组件集的Apache Camel对于需要通过不同协议(如文件、api或JMS队列)与系统集成的应用程序非常有用。
  • Apache Camel的实现了企业集成模式,满足非常复杂的集成场景。
  • 微服务中的编排和编排可以用Apache Camel路由中的领域特定语言来定义。路由有助于保持核心业务逻辑与通信逻辑解耦,并满足SRP(单一责任原则)。
  • Apache Camel非常适合Java和Spring应用程序。
  • 使用Java对象(pojo): Apache Camel是一个Java框架,因此它特别擅长使用Java对象。因此,如果使用的是XML、JSON等文件格式,可以反序列化为Java对象,那么Camel就可以轻松地对其进行处理。

◆ 不适合使用Apache Camel的场景:

  • 如果我们的集成只是简单调用少量api
  • Camel在处理大量数据时表现不佳
  • Camel也不适合缺乏Java技能的团队

一般来说,camel的最佳用例是,有一个数据源,我们希望从其中消费数据,比如队列上的传入消息,或者从API和目标中获取数据,我们希望将数据发送到这些数据源。

http://www.lryc.cn/news/109241.html

相关文章:

  • 2023奇安信天眼设备--面试题
  • 【剑指Offer 58】 左旋转字符串,Java解密。
  • Python SMTP发送邮件
  • Jmeter-获取接口响应头(Response headers)信息进行关联
  • 解密爬虫ip是如何被识别屏蔽的
  • GPIO实验
  • Docker-Compose编排与部署(lnmp实例)
  • Docker 网络模型使用详解 (1)Dockers网络基础
  • 【Spring】(四)Bean 的作用域和生命周期
  • 卷积神经网络【图解CNN】
  • 命令模式 Command Pattern 《游戏设计模式》学习笔记
  • 供水管网漏损监测,24小时保障城市供水安全
  • How to Use Glslang
  • AcWing 24:机器人的运动范围 ← BFS、DFS
  • RF手机天线仿真介绍(一):金属边框天线和LDS天线
  • 动手学深度学习—深度学习计算(层和块、参数管理、自定义层和读写文件)
  • Pytest学习教程_测试报告生成pytest-html(三)
  • 模块化原理:source-map
  • 【C++】开源:ncurses终端TUI文本界面库
  • C语言的_Bool类型
  • 【python爬虫】获取某一个网址下面抓取所有的a 超链接下面的内容
  • AutoDL从0到1搭建stable-diffusion-webui
  • 手动调整broker扩容后的旧topic分区
  • 【LeetCode-简单】剑指 Offer 25. 合并两个排序的链表(详解)
  • Java版工程行业管理系统源码-专业的工程管理软件-em提供一站式服务
  • 【Spring】简化事件的使用,Spring提供了2种使用方式
  • 探究Spring事务:了解失效场景及应对策略
  • Maven Manifold 条件编译
  • 4.数组与基本数学函数
  • python与深度学习(十六):CNN和宝可梦模型二