规则引擎(Drools):
1、 规则文件结构:
1 package :规则文件的包名,定义一个名称空间。(package必须定义在规则文件的最前面,其他可以自由定义)
2 import: 声明规则在编译和运行时所用到的java类。默认会导入相同包名的全部的java类和java.lang包下的全部类。
如果需要的java类和规则文件定义的包名相同,则不需要显示的导入。
3 global:用于定义全局变量(数据或服务对象),一般用于存放规则结果或者与应用进行数据交互。
4 function:用于在规则文件中定义逻辑语句,可以将部署逻辑独立存放到规则文件中,供多个规则调用。
5 queryL:使用查询可以到工作存储空间中查找符合条件的事实数据。(事实数据均会被存储到工作存储空间中)
6 rule:一个rule定义一个业务规则:条件称为:LHS,行为称作:RHS, 使用:when LHS then RHS。
2、 关键字:
硬关键字:共三个:true , false 和null。约束性较强,不允许用来命名规则元素。
软关键字:四十个:可以但建议不要使用软关键字进行命名。
3、 规则编译:
向KonwledgeBuilder添加规则资源时,KnowledgeBuilder会将解析到的规则内容进行编译,如有语法错误,会封装到KnowledgeBuilderResult的集合,
放到Package的实例中。可以使用KnowledgerBuilder的getError方法获取PackageBuilderErrors实例,调用toString 方法查看错误信息。
4、声明新类型:(实例)
declare Person (declare关键字声明) extendsOrginalPerson (支持继承)
@age(33)
name: String (属性声明方式:“属性名:类型”,类型可以为基本数据类型和对象)
age: int
Weight: java.math.BigDecimal (对象使用全限定类名,可有不用import导入对象,否则需要显示导入)
end (以"end"表示结束)
5 声明元数据:(可以用于规则引擎和推理引擎查询)
声明格式:@元数据名称(元数据值)
6 函数的定义和使用,及查询的定义和使用:
函数的定义:function关键字定义,可以再LHS和RHS中调用函数。可以在规则中使用定义的java类的静态方法。
查询的定义:query关键字定义,获取查询的对象需要传入查询中定义的实例标识。
7 规则语法:
1 全局变量 :
使用“global”关键字定义。在规则中,可以使用全局变量的方法和数据,也可以从规则的执行中得到相应的结果数据。
全局变量不会被写入到Working Memory中,不能在规则条件中使用。全局变量更多会用来存放规则结果,作为应用程序和规则之间
的交互桥梁。
定义的全局变量在使用时,需要进行初始化(调用setGlobal() 方法设置):如:
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ksession.setGlobal("maxThan30",new ArrayList<Person>());
如果在规则行为中进行了赋值操作,则不需要进行初始化操作。
2 规则属性
no-loop:默认为false,表示事实对象发生变化时,总会重新匹配该规则。
ruleflow-group:指定某个流程节点使用的规则组。
agenda-group:为规则设定所属的规则组。当规则组获得焦点时,则匹配组内的规则,如果规则组没有获得焦点,则不会触发,默认值为MAIN。
lock-on-active:在一个规则组内,如果一个规则被触发,则使用该属性会判断是否再次触发该规则,为true,则表示不需要再触发这个规则(即符合条件)
auto-focus:如果该属性值为true并且规则符合触发条件,则该规则所在的规则组将会自定获得焦点。默认为false。
activation-group:如果多个规则配置了相同的激活组,则这些规则中只会有一个规则被激活。
salience:默认值为0,该属性配置规则的优先级,属性值越大,规则匹配的优先级越高,可以为负数。
dialect:指定LHS和RHS的表达式方言,当前支持java和mvel,规则中的方言默认和包中指定的方言一致。
date-effective:规则的生效时间,规则将会在该时间之后被触发。
date-expires:规则的有效时间(结束时间),在有效时间之后,规则将不会被触发。
duration:如果一个规则服符合触发条件,那么该属性配置规则被匹配后触发的延迟时间。
3 条件语法
可以直接判断一个对象的属性值,多个属性值以及集合元素等。也可以在条件语句中,直接为事实实例或者属性定义名称,
在行为语句中使用。将条件语句看作一个整体,根据这个整体的最终解雇来判断规则是否执行。
4 行为语法
执行语句用于执行规则触发后的工作。不推荐在行为语句中加入逻辑判断。
Activiti调用规则
使用Activiti中的业务规则任务可以执行一个或者多个业务规则,当前activiti只支持Drools。Activiti在实例化业务规则任务行为时,只需要调用Drools的API,
即可实现规则文件的加载、事实实例的插入,跪着触发等操作。任务的定义者只需要提供参数、规则和计算结果等。
1 业务规则任务
规则文件会被看作资源,被保存在ACT_GE_BYTEARRAY表中。因此在部署流程资源文件时,需要提供这些规则文件。
activiti中对应的行为的实现类:BusinessRuleTaskActivityBehavior。
代码过程实例:
//创建一个KnowledgeBuilder
KnowledgeBuilderkbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
//添加规则资源到KnowledgeBulider
kbuilder.add(ResourceFactory.newClassPathResource("rule/MyDoors.drl",FirstTest.class),ResourceType.DRL);
if(kbuilder.hasErrors()){
System.out.println(kbuilder.getError().toString());
System.exit(0);
}
//获取知识包集合
Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();
此处后的功能由BusinessRuleTaskActivityBehavior完成(代码完成不同)
KnowledgeBase的实例创建将由activiti的其他类完成。
//创建KnowledgeBase实例
KnowledgeBase kbase = kbuilder.newKnowledgeBase();
//将知识包部署到KnowledgeBase中
kbase.addKnowledgePackages(pkbs);
//使用KnowledgeBase创建StatefulKnowledgeSession
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
//创建事实
Person p1 = new Person("person 1",11);
//插入到working memory
ksession.insert(p1);
//匹配规则
ksession.fireAllRules();
//关闭当前的session资源
ksession.dispose();
2 activiti调用规则步骤:
1 定义相应的javaBean实体类
2 定义需求的规则文件
3 在流程资源文件中添加<businessResultTask>
设置输入参数:ruleVariableInput = "${sale1},${sale2}"
设置返回结果:resultVariable = "saleResults"
4 部署规则文件(.drl)
repositoryService.createDeployment()
.addClasspathResource("rule/sale.drl")
.addClasspathResource("bpmn/saleRule.bpmn")
.deploy();
5 在activiti.cfg.xml配置加入规则文件的部署实现类
<property name = "customPostDeployers">
<list>
<bean class= "org.activiti.engine.impl.rules.RulesDeployer" />
</list>
</property>
6 业务规则任务完成后,执行流会到达一个Service Task。
文章摘致于:疯狂workflow讲义 基于activiti工作流的应用开发