概述
规则引擎起源于基于规则的专家系统,而基于规则的专家系统又是专家系统的其中一个分支。专家系统属于人工智能的范畴,它模仿人类的推理方式,使用试探性的方法进行推理,并使用人类能理解的术语解释和证明它的推理结论。
利用它就可以在应用系统中分离商业决策者的商业决策逻辑和应用开发者的技术决策,并把这些商业决策放在中心数据库或其他统一的地方,让它们能在运行时可以动态地管理和修改,从而为企业保持灵活性和竞争力提供有效的技术支持。
在需求里面往往把约束,完整性,校验,分支流等都可以算到业务规则里面。在规则引擎里面谈的业务规则重点是谈当满足什么样的条件的时候,需要执行什么样的操作。因此一个完整的业务规则包括条件和触发操作两部分内容。而引擎是事物内部的重要的运行机制,规则引擎即重点是解决规则如何描述,如何执行,如何监控等一系列问题。
规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。
优点
- 声明式编程:规则可以很容易地解决困难的问题,并得到解决方案的验证。与代码不同,规则以较不复杂的语言编写,业务分析师可以轻松阅读和验证一套规则;
- 逻辑和数据分离:数据位于域对象中,业务逻辑位于规则中;
- 速度和可扩展性:写入Drools的Rete OO算法已经是一个成熟的算法。如果频繁更改请求,可以添加新规则,而无需修改现有规则
- 知识集中化:通过使用规则,您创建一个可执行的知识库(知识库)。理想情况下,规则是可读的,它们也可以用作文档
Rete算法
最初是由卡内基梅隆大学的Charles L.Forgy博士在1974年发表的论文中所阐述的算法,该算法提供专家系统的一个高效实现。自Rete算法提出以后,它就被用到一些大型的规则系统中,像ILog、Jess、JBoss Rules等都是基于RETE算法的规则引擎。
Rete,在拉丁语中译为net,即网络。Rete匹配算法是一种进行大量模式集合和大量对象集合间比较的高效方法,通过网络筛选的方法找出所有匹配各个模式的对象和规则。
其核心思想是将分离的匹配项根据内容动态构造匹配树,以达到显著降低计算量的效果。Rete算法可以被分为两个部分:规则编译和规则执行。当Rete算法进行事实的断言时,包含三个阶段:匹配、选择和执行,称做match-select-act cycle。
rate算法参考:开源规则流引擎实践
Java开源的规则引擎有:Drools、Easy Rules、Mandarax、IBM ILOG。
Drools
官网,易于访问企业策略、易于调整及易于管理的开源(GitHub,6.3K Star,2.6K Fork)业务规则引擎,符合业内标准,速度快、效率高。用Java语言编写,使用Rete算法对所编写的规则求值。允许使用声明方式表达业务逻辑。可使用非XML的本地语言编写规则,从而便于学习和理解。还可将Java代码直接嵌入到规则文件中,业务分析师人员或审核人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行所需的业务规则。
优势:
易用、执行速度快、兼容Java Rule Engine API,即JSR 94。
概念:
事实:Fact,对象之间及对象属性之间的关系
规则:Rule,是由条件和结论构成的推理语句,一般表示为if…Then。一个规则的if部分称为LHS,then部分称为RHS。
模式:Module,指IF语句的条件。IF条件可能是有几个更小的条件组成的大条件。模式就是指的不能在继续分割下去的最小的原子条件。
依赖:
<dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId></dependency>Drools通过事实、规则和模式相互组合来完成工作。有专门的规则语法drl,就是专门描述活动的规则是如何执行的。
DSL
Domain Specific Language
.drl、.dslr或.xls文件
规则语言
一个规则通常包括三个部分:属性部分( attribute)、 条件
部分( LHS)和结果部分( RHS)
规则流
宏对象
实战
用户支付金额和对应送多少积分的规则如下:
100元(含)以下,不加分 100元-500元(含),加100分 500元(不含)以上,加500分写出的规则文件point-rulesKS.drl:
package rulesimportcom.johnny.drools.entity.Order rule"zero"no-looptruelock-on-activetruesalience1when$s:Order(amout<=100)then$s.setScore(0);update($s);end rule"add100"no-looptruelock-on-activetruesalience1when$s:Order(amout>100&&amout<=500)then$s.setScore(100);update($s);end rule"add500"no-looptruelock-on-activetruesalience1when$s:Order(amout>500)then$s.setScore(500);update($s);end说明:
- package:与Java语言类似,drl的头部需要有package和import的声明,package不必和物理路径一致
- import:导出Java Bean的完整路径,也可以将Java静态方法导入调用
- rule:规则名称,需保持唯一性,可以无限次执行
- no-loop:定义当前的规则是否不允许多次循环执行,默认是false,也就是当前的规则只要满足条件,可以无限次执行
- lock-on-active:设置为true,可避免因某些Fact对象被修改而使已经执行过的规则再次被激活执行
- salience:用来设置规则执行的优先级,值是一个数字,可以是负数,数字越大执行优先级越高。默认为0。如果不设置规则的salience 属性,那么执行顺序是随机的
- when:条件语句,当到达什么条件时
- then:根据条件的结果,来执行什么动作
- end:规则结束
放置在resources/META-INF/kmodule.xml目录下的配置文件告诉代码规则文件drl在哪里:
<kmodule><kbasename="point-rulesKB"packages="rules"><ksessionname="point-rulesKS"/></kbase></kmodule>解释:
- Kmodule:可以包含一个到多个 kbase,分别对应 drl 的规则文件
- Kbase:需要一个唯一的name,可以取任意字符串
- packages为drl文件所在resource目录下的路径。注意区分drl文件中的package与此处的package不一定相同。多个包用逗号分隔。默认情况下会扫描 resources目录下所有(包含子目录)规则文件
- kbase的default属性,标示当前KieBase是不是默认的,如果是默认的则不用名称就可以查找到该 KieBase,但每个 module 最多只能有一个默认 KieBase
- kbase:可以有一个或多个ksession,ksession 的name属性必须设置,且必须唯一
publicstaticvoidmain(String[]args)throwsException{KieServicesks=KieServices.Factory.get();KieContainerkc=ks.getKieClasspathContainer();execute(kc);}privatestaticvoidexecute(KieContainerkc)throwsException{KieSessionksession=kc.newKieSession("point-rulesKS");ksession.insert(null);ksession.fireAllRules();ksession.dispose();}首先请求获取KieServices,通过KieServices获取KieContainer,KieContainer加载规则文件并获取KieSession,KieSession来执行规则引擎,KieSession是一个轻量级组件,每次执行完销毁。KieContainer是重量级组建,需考虑复用。
概念
Fact对象
API
规则编译、规则收集和规则执行
KnowledgeBuilder
KnowledgeBase
StatefulKnowledgeSession
StatelessKnowledgeSession
KnowledgeBaseConfiguration
规则属性
不完全列表
| 属性名称 | 默认值 | 解释 |
|---|---|---|
| activation-group | 激活分组 | |
| agenda-group | 议程分组 | |
| auto-focus | false | |
| date-effective | 生效时间 | |
| date-expires | 失效时间 | |
| dialect | Java或Mvel | |
| duration | 定时器 | |
| enabled | true | 设置为false,则规则体将不被激活 |
| lock-on-active | false | 设置为true,当前只会被触发一次。解决死循环 |
| no-loop | false | 设置为true,避免当前规则then部分被修改后的事实对象再次被激活,从而防止死循环的发生,即执行下面的规则 |
| ruleflow-group | 规则、流程、分组,即规则流 | |
| salience | 0 | 规则体被执行的顺序。不设置salience属性,规则体的执行顺序为由上到下。salience可以是负数,值越大,执行顺序越高 |
| timer |
关键词
有硬关键词和软关键词之分。
硬关键字主要包括true、false、null,规则文件不能使用。
软关键词,在规则文件里可以使用,但是得以驼峰命名格式作为字段名的部分,如someRule。包括:lock-on-active、date-effective、date-expires、no-loop、auto-focus、activation-group、agenda-group、ruleflow-group、entry-point、duration、package、import、dialec、salience、enabled、attributes、rule、extend、template、query、declare、function、global、eval、not、in、or、and、exists、forall、action、reverse、result、end、init等。