drools数据库
‘壹’ Drools规则引擎
Drools规则引擎1.什么是规则引擎规则引擎的主要思想是将应用程序中的业务决策部分抽离出来,并使用预定义的语义模块编写业务决策,由用户或开发者在需要时进行配置管理。规则引擎产品有Drools、VisualRules、iLog等。
例如,在信用卡申请业务中,需要根据学历、收入、是否有房、是否有车判断是否符合信用卡申请要求以及可以申请的额度是多少。传统的做法是使用if...else的做法,代码量大,且不易修改。
规则引擎实现将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎就是一个输入到输出的平台。
信用卡申请业务通过规则引擎的处理就变成了这样:
系统引入规则引擎之后,业务规则不再以程序代码的方式驻留在系统中,取而代之的是处理规则的规则引擎,业务规则存储在规则库中,完全独立于程序。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更改、统计、提交业务规则等。业务规则被加载到规则引擎后,供系统的应用程序调用。
2.规则引擎的优势业务代码与系统代码分离,实现业务规则的集中管理;
在不重启服务的情况下,可以随时对业务规则进行扩展和维护;
可以动态修改业务规则,从而快速响应需求变更;
规则引擎是相对独立的,只关心业务规则,使得业务分析人员也可以参与编辑、维护系统的业务规则;
减少了硬编码业务规则的成本和风险;
还可以使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得简单。
3.规则引擎的应用场景业务规则复杂,且经常变动。
(1)风险控制系统--风险贷款、风险评估
(2)反欺诈项目--银行贷款、征信验证
(3)决策平台系统--财务计算
(4)促销平台系统--满减、打折、加价购
4.Drools介绍Drools是一款由JBoss组织提供的基于java语言开发的开源规则引擎,可以将复杂多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或者指定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。IDEA中集成了Drools的插件,eclipse开发需要单独安装Drools 的插件。
Drools API开发步骤:
获取KieServices
获取KieContainer
获取KieSession
插入Fact对象
触发规则
关闭KieSession
//1.获取KieServicesKieServices kieServices = KieServices.Factory.get();//2.获取Kie容器对象KieContainer kieContainer = kieServices.getKieClasspathContainer();//3.从kie容器对象中获取会话对象KieSession session = kieContainer.newKieSession();//4.创建Fact对象(事实对象)Proct proct = new Proct();proct.setType("diamond");//5.将Proct对象插入到工作内存中去session.insert(proct);//6.激活规则,由drools框架自动进行规则匹配,如果匹配成功,则执行规则session.fireAllRules();//7.关闭sessionsession.dispose();5.规则引擎的构成working Memory(工作内存)
Rule Base(规则库)
Inference Engine(推理引擎):Pattern Matcher(匹配器)、Agenda(议程)、Execution Engine(执行引擎)
6.规则引擎执行过程将初始数据(fact)输入至工作内存(working Memory)
使用匹配器(Pattern Matcher)将规则库中的规则(rule)和数据(fact)匹配,匹配成功的放入到议程(Agenda)中
如果执行规则存在冲突,即同时激活了多个规则,将冲突的规则放入冲突集合(冲突是同时匹配了多条规则,不需要自己处理,drools会自动处理)
解决冲突,将激活的规则按顺序放入议程(Agenda)
执行议程(Agenda)中的规则,重复2-4,直到执行完毕议程中的所有规则
7.规则文件的构成package:包名,package对应的不一定是真正的目录,可以任意写com.abc,同一个包下的drl文件可以相互访问
import:用于导入类或者静态方法
global:全局变量
function:自定义函数
query:查询
rule end:规则体
8.规则体语法结构rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束9.Drools基础语法< >= <=>contains:检查一个Fact对象的某个属性值是否包含一个指定的对象值
not contains:检查一个Fact对象的某个属性值是否不包含一个指定的对象值
memberOf:判断一个Fact对象的某个属性是否在一个或多个集合中
not memberOf:判断一个Fact对象的某个属性是否不在一个或多个集合中
matches:判断一个Fact对象的属性是否与提供的标准的Java正则表达式进行匹配
not matcher:判断一个Fact对象的属性是否不与提供的标准的Java正则表达式进行匹配
10.Drools内置方法规则文件的RHS部分的主要作用是通过插入、删除或修改工作内存中的Fact数据,来达到控制规则引擎执行的目的。Drools提供了一些方法可以用来操作工作内存中的数据,操作完成后规则引擎会重新进行相关规则的匹配,原来没有匹配成功的规则在我们修改数据完成后有可能就会匹配成功了。
(1)update方法
update方法的作用是更新工作内存中的数据,并让相关的规则重新匹配。更新数据时,要注意防止陷入死循环。
rule "年龄小于十岁"when $student:Student(age<10)then $student:setAge(15)update($student)//update方法用于更新Fact对象,会导致相关规则重新匹配end(2)insert方法
insert方法的作用是向工作内存中插入数据,并让相关的规则重新匹配
rule "年龄等于十岁"when $student:Student(age==10)thenStudent s = new Student(); s.setAge(5);insert(s);//insert方法的作用是向工作内存中插入Fact对象,会导致相关规则重新匹配end(3)retract方法
retract方法的作用是删除工作内存中的数据,并让相关的规则重新匹配
rule "年龄等于十岁"when $student:Student(age==10)then retract($student)//retract方法的作用是删除工作内存中的Fact对象,会导致相关规则重新匹配end11.规则属性salience:指定规则执行的优先级,用数字表示,数字越大优先级越高。如果不设置,默认从上到下执行
dialect:指定规则使用的语言类型,java或mvel
enabled:指定规则是否启用,取值为ture或false,默认为true
date-effective:指定规则生效的时间
date-expires:指定规则失效的时间
timer:定时器,指定规则触发的时间
activation-group:激活分组,同一个组内只能有一个规则触发
agenda-group:议程分组,只有获取焦点的组中的规则才有可能触发。在java代码中获得焦点。
session.getAgenda().getAgendaGroup("agenda_group_name").setFocus;auto-focus:自动获取焦点,一般结合agenda-group使用,取值为ture或false
no-loop:防止死循环,当规则使用update之类的函数修改了Fact对象时,使当前规则再次被激活从而导致死循环。
12.Drools高级语法1.global全局变量
global关键字用于在规则文件中定义全局变量,它可以让应用程序的对象在规则文件中能够被访问。可以用来为规则文件提供数据或服务。语法结构:global 对象类型 对象名称。
注意事项:如果对象类型为包装类时,在一个规则中改变了global的值,那么只针对当前规则有效,对其他规则中的global不会有影响。如果对象类型为集合类型或者javaBean时,在一个规则中改变了global的值,对java代码和所有规则都有效。
2.query查询
query查询提供了一种查询working memory中符合约束条件的Fact对象的简单方法。它仅包含规则文件中的LHS部分,不用指定"when"和"then"部分并且以end结束。具体语法结构如下:
query 查询的名称(可选参数)LHSend3.function函数
function关键字用于在规则文件中定义函数,规则体中可以调用定义的function函数。使用函数的好处是可以将业务逻辑集中放置在一个地方,根据需要可以对函数进行修改。
function 返回值类型 函数名(可选参数){//逻辑代码}4.LHS语法
(1)复合值限制in/not in
复合值限制是指超过一种匹配值的限制条件,类似于SQL语句中的in关键字。
$s:Student(name in ("张三","李四","王五"))$s:Student(name not in ("张三","李四","王五"))(2)条件元素eval
eval用于规则体的LHS部分,并返回一个Boolean类型的值。语法结构:eval(表达式)
eval(1==1)(3)条件元素not
not用于判断working memory中是否存在某个Fact对象,如果不存在则返回true,存在返回true。
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束0(4)条件元素exists
exists与not相反,用于判断working memory中是否存在某个Fact对象,如果存在则返回true,不存在返回true。
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束1(5)规则继承
规则之间使用extends关键字进行规则部分的继承,类似于java类之间的继承。
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束25.RHS语法
RHS部分需要进行业务处理。在RHS部分Drools提供了一个内置对象,名称是drools,介绍几个drools对象的方法。
(1)halt
halt方法的作用是立即终止后面所有规则的执行。
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束3(2)getWorkingMemory
getRule方法的作用是返回工作内存中的对象。
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束4(3)getRule
getRule方法的作用是返回规则对象。
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束513.规则文件编码规范所有的规则文件(.drl)应统一放在一个规定的文件夹汇总,如:/rules文件夹
书写的每一个规则应该尽量加上注释
同一类型的对象尽量放在一个规则文件中,如所有的Student类型的对象尽量放在一个规则文件中
规则结果部分(RHS)尽量不要有条件语句,尽量不要有复杂的逻辑和深层嵌套
每个规则最好都加上salience属性,明确执行顺序
Drools默认dialect为"java",尽量避免使用dialect "mvel"
14.Spring Boot整合Drools----以信用卡申请为例创建maven工程creditCardApply,并配置pom.xml
创建resources/application.yml文件
创建entity/CreditCardApply.java实体类
创建resources/rules/CreditCardApply.drl文件
编写配置类config/DroolsConfig.java
创建RuleService.java
创建RuleController.java
具体代码如下:
(1)创建maven工程creditCardApply,并配置pom.xml
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束6(2)创建resources/application.yml文件
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束7(3)创建entity/CreditCardApply.java实体类
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束8(4)创建resources/rules/CreditCardApply.drl文件
rule "ruleName"//rule关键字,表示规则开始,参数为规则的唯一名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后面是规则的条件部分LHS//Left Hand Side,是规则的条件部分then //后面跟规则的结果部分RHS//是规则的结果或行为end//表示一个规则的结束9(5)编写配置类config/DroolsConfig.java
rule "年龄小于十岁"when $student:Student(age<10)then $student:setAge(15)update($student)//update方法用于更新Fact对象,会导致相关规则重新匹配end0(6)创建RuleService.java
rule "年龄小于十岁"when $student:Student(age<10)then $student:setAge(15)update($student)//update方法用于更新Fact对象,会导致相关规则重新匹配end1(7)创建RuleController.java
rule "年龄小于十岁"when $student:Student(age<10)then $student:setAge(15)update($student)//update方法用于更新Fact对象,会导致相关规则重新匹配end2原文:https://juejin.cn/post/7099467623000784926‘贰’ drools的规则实例到底指的是什么
InfoQ发布了一个关于规则引擎的介绍Real-World Rule Engines,原文
ONJava上也有两篇文章:
Give Your Business Logic a Framework with Drools
Using Drools in Your Enterprise Java Application
下面总结一下其中的精华:
大多数web和企业Java应用可以分成三个部分:一个和用户交互的前台, 一个和后台系统,例如数据库交互的服务层,以及他们中间的业务逻辑。 现在使用框架构建前台和后台系统已经成为普遍共识(例如, Struts, Cocoon, Spring, Hibernate, JDO, 和 Entity Beans), 但却没有一个标准的方法来构建业务逻辑。一些框架,例如 EJB 和 Spring 只在一个高层实现业务逻辑,但对于我们组织逻辑代码没有任何帮助,所以,为什么没有一个框架来替换冗繁,易错的if...then语句呢,这个框架应该和其它前台或后台框架一样,易于配置,具有可读性和重用性。下面我们将介绍Drools 规则引擎,这个来解决我们问题的框架。
下面是一个典型的Java业务逻辑的代码
if ((user.isMemberOf(AdministratorGroup)
&& user.isMemberOf(teleworkerGroup))
|| user.isSuperUser(){
// more checks for specific cases
if((expenseRequest.code().equals("B203")
||(expenseRequest.code().equals("A903")
&&(totalExpenses<200)
&&(bossSignOff> totalExpenses))
&&(deptBudget.notExceeded)) {
//issue payments
} else if {
//check lots of other conditions
}
} else {
// even more business logic
}
这是大多数程序员写业务逻辑的方法,但是有以下的问题:
如果用户有另一个选项,例如("C987") ,那么需要修改上面的代码,当代码很长的时候,修改代码是难于维护的
我们如何保证代码的正确性,这个代码只有程序员能够看到,真正的使用者,业务人员无法看到这个代码
很多应用程序有相同的业务逻辑,如果某个业务改变了,如何保证其他业务逻辑的一致性
业务逻辑能否不合java语言绑定?
业务逻辑能否用其他的脚本语言。
Java下的规则引擎标准就是JSR94,它的实现主要有Jess Jena Drools
Drools中,一个典型的业务逻辑的配置,如下
<?xml version="1.0"?>
<rule-set name="BusinessRulesSample"
xmlns=""
xmlns:java=""
xmlns:xs
=""
xs:schemaLocation
=" rules.xsd
java.xsd">
<!-- Import the Java Objects that we refer
to in our rules -->
<java:import>
java.lang.Object
</java:import>
<java:import>
java.lang.String
</java:import>
<java:import>
net.firstpartners.rp.StockOffer
</java:import>
<!-- A Java (Utility) function we reference
in our rules-->
<java:functions>
public void printStock(
net.firstpartners.rp.StockOffer stock)
{
System.out.println("Name:"
+stock.getStockName()
+" Price: "+stock.getStockPrice()
+" BUY:"
+stock.getRecommendPurchase());
}
</java:functions>
<rule-set>
<!-- Ensure stock price is not too high-->
<rule name="Stock Price Low Enough">
<!-- Params to pass to business rule -->
<parameter identifier="stockOffer">
<class>StockOffer</class>
</parameter>
<!-- Conditions or 'Left Hand Side'
(LHS) that must be met for
business rule to fire -->
<!-- note markup -->
<java:condition>
stockOffer.getRecommendPurchase() == null
</java:condition>
<java:condition>
stockOffer.getStockPrice() < 100
</java:condition>
<!-- What happens when the business
rule is activated -->
<java:consequence>
stockOffer.setRecommendPurchase(
StockOffer.YES);
printStock(stockOffer);
</java:consequence>
</rule>
</rule-set>
一条规则就是rule-set中的rule,如果有很多规则,就要写很多的rule。
上面规则的意思是判断股票价格是否小于100,如果100这个标准改变了,那么只要修改这个规则文件,而不用去修改源代码了
‘叁’ 正在学习Drools规则引擎,一直出现空指针问题,想请教一下各位大神
而是在数据库表中进行配置。因此我们常见的业务逻辑层的开发,并不能先设计出一个数据模型,然后再在此基础上抽象逻辑。但我们确实解决了业务逻辑层的业务逻辑配置问题。应该说我们的更实用一些。但是我们却没法去实现JSR94标准。我们不光处理业务逻辑。
我们以JBoss的Drools为例,再打包成一个规则包,也提到了规则引擎。
在我们的印象中,我们感觉规则引擎就是解决业务逻辑层的实现问题的。因此我们理所当然的觉得工作流中的某个节点的逻辑处理,应该可以用规则引擎来解决。但是也使得规则引擎的应用得到了很大的限制。
首先这种抽象本身需要一个复杂的分析过程,这需要有很强的分析设计能力。另外我们平时具体应用中的业务逻辑层,大量的逻辑都是对实际数据的处理,很多时候还是一个批量数据的处理,甚至有些逻辑需要的参数我们并不能定义在规则中。
因此我们发现Drools等规则引擎很难用,根本不是我们所需要的那样。有时候我们发现自己做的规则引擎并不是一个规则引擎。因为我们和像Drools这些规则引擎有很大的差别。
我们研究规则引擎也有一段时间了可能很多人还不了解规则引擎是什么东西,或者不知道规则引擎究竟有什么用。一个规则包相当于一个智能块。首先需要将我们具体应用中的业务逻辑做抽象,抽象成一条条规则之后。
但是当我们在使用上述这些规则引擎,却发现很难和我们实际应用的业务逻辑层的业务逻辑实现相对应。我们都知道工作流引擎,也听说过JBoss下面有个Drools,或者我们知道 weblogic或者Oracle也有自己的Business Rule,我们可能还听说过ILOG被IBM收购了,如果我们研究微软的WWF。当数据传递给这个智能块后,系统会以匹配的方式应用满足条件的逻辑处理。
当采用这种方式时,应该说逻辑更抽象了,在一个更高的层次加以抽象化的定义,那么工作流本身的逻辑也应该可以由规则引擎来解决,可能也知道其中有RuleSet等内容。国内的一些web快速开发平台,由于其规则引擎使用了匹配规则的方式来进行,因此在应用这些规则引擎时。另外我们也会觉得,平时项目当中的业务逻辑应该都可以用规则引擎来解决,还把所有业务逻辑层需要处理的操作全部采用规则配置的形式
‘肆’ 规则引擎drools如何整合spring,drl文件一般放在什么地方
drl文件可以持久化到数据库中,然后写个加载执行的引擎,这样可以很灵活的结合实际业务。
先写规则模板,采用velocity解析,通过规则解析后,生产规则文件,规则文件就是drools文件。
规则模板和规则文件统一持久化到数据库中。
‘伍’ drools 我这边根据需求需要做到可以在web页面随意改动规则..我目前想到的办法是通过java生成drl文件.
试试Drools Guvnor, http://www.jboss.org/drools/drools-guvnor.html