最近项目用到了规则流踩了一些小坑,特以记录。
代码写好了再放到规则文件中,规则流最好一步一步画,因为错了就给你抛看不懂没意义的异常。
所有的包包括List这种都得引。
我自己也一知半解,本文都是一些小细节,如有错漏,欢迎指正。
1.文档
官网:https://www.drools.org/
官方文档:https://nheron.gitbooks.io/droolsonboarding/content/gettingStarted/drools.html <-- lesson 4
GitHub:https://github.com/kiegroup/droolscourse
参考了很多人的博客 ,记不全了
https://blog.csdn.net/tian6318/article/details/78569388
https://blog.csdn.net/wo541075754/article/category/6397798
以前规则流是用Drools自己的.rf文件,现在用bpmn2 参考以下回答。
https://stackoverflow.com/questions/16698617/difference-between-rf-and-bpmn2
2.Intellj idea
如果使用Intellj idea来使用drools到没有什么问题,bpmn打开很别扭啊,劝退劝退
(1)官方视频 https://screencast-o-matic.com/watch/cbfFXsX1gX
过程就是安装jboss jpmn
然后改打开方式
可是这样 全都堆在一起,看官方视频可能mac支持的好?
(2)如果用actiBPM ,倒是可以正常用,但是这查看xml和生成png的方式也是绝了。
可以看这个 https://blog.csdn.net/qq_35463719/article/details/82967287
生成png: https://blog.csdn.net/wk52525/article/details/79362904
下面开始正文
一. 安装
可以参考https://blog.csdn.net/shenhaiwen/article/details/70230103
我用的是eclipse mars,安装以下插件
https://download.jboss.org/drools/release/7.5.0.Final/org.drools.updatesite/
二. 使用
最简单的方式,建一个drool project 选带例子的 先了解一下大概的结构,就是有点旧。
三. 规则和规则流搭配使用
按我自己的理解,规则流(bpmn2)里应该画一些“比较条件”,这些条件可能会变化,图像的形式更容易让人理解。
规则(drl)里写一些固定的结果,比如说当某种情况下,执行某些行为 判断情况写在bpmn里 执行结果写在drl里
(以下springboot工程)
pom 添加
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.jbpm</groupId>
<artifactId>jbpm-bpmn2</artifactId>
<version>7.0.0.Final</version>
</dependency>
目录机构
建议先画一个只有开始结束的规则流,验证一下好不好使,再添加步骤。
(1) 新建drl
注意包的引用 !!!
package process
import java.util.Calendar;
import java.util.Date;
import com.summer.my.droolsproject.Fact.PersonFact;
rule "age-rule"
ruleflow-group "age-check-group"
lock-on-active true
when
p:PersonFact()
then
System.out.println("hello"+p.getName());
if(p.getBirthday()!=null){
int age =0;
Calendar now = Calendar.getInstance();
now.setTime(new Date());
Calendar birth = Calendar.getInstance();
birth.setTime(p.getBirthday());
if (birth.after(now)) {
age = 0;
} else {
age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
if (now.get(Calendar.DAY_OF_YEAR) > birth.get(Calendar.DAY_OF_YEAR)) {
age += 1;
}
}
p.setAge(age);
}
end
rule "teenager-rule"
ruleflow-group "teenager"
lock-on-active true
when
p:PersonFact()
then
System.out.println(p.getName()+"是一名青少年");
end
rule "adult-rule"
ruleflow-group "adult"
lock-on-active true
when
p:PersonFact()
then
System.out.println(p.getName()+"是一名成年");
end
(2) META-INF 文件夹 新建kmodule.xml
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="process" packages="process">
<ksession name="ksession-process"/>
</kbase>
</kmodule>
(3) 新建bpmn2 ??用bpmn2建也行?标签不一样
bpmn中的内容 有start 经过task
箭头所指的部分要对应规则(drl)中的 ruleflow-group 指定执行的规则组
注意箭头选项,优先级,和condition的语言
在规则流里用的类需要import
AppTest 规则和流都放在process下,如果分开放是不是得指定上级的包啊,要不kSession的package定义多个包?
package com.summer.my.droolsproject;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import com.summer.my.droolsproject.Fact.PersonFact;
/**
* Unit test for simple App.
*/
public class AppTest{
@Test
public void testOne(){
try {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-process");
PersonFact person = new PersonFact();
person.setName("李某某");
person.setBirthday(DateUtils.parseDate("1999-01-01","yyyy-MM-dd"));
kSession.insert(person);
kSession.startProcess("process.myProcess");
kSession.fireAllRules();
kSession.dispose();
System.out.println(person.getName()+"的年龄是:"+person.getAge());
} catch (Throwable t) {
t.printStackTrace();
}
}
}
输出结果
以xml形式查看规则流
<?xml version="1.0" encoding="UTF-8"?>
<!-- origin at X=0.0 Y=0.0 -->
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:java="http://www.java.com/javaTypes" xmlns:tns="http://www.jboss.org/drools" xmlns="http://www.jboss.org/drools" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd http://www.jboss.org/drools drools.xsd http://www.bpsim.org/schemas/1.0 bpsim.xsd" id="Definition" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.2.5.Final-v20160831-1132-B114" expressionLanguage="http://www.mvel.org/2.0" targetNamespace="http://www.jboss.org/drools" typeLanguage="http://www.java.com/javaTypes">
<bpmn2:itemDefinition id="ItemDefinition_2" isCollection="false" structureRef="com.summer.my.droolsproject.Fact.PersonFact"/>
<bpmn2:process id="process.myProcess" tns:packageName="process" name="myProcess" isExecutable="true" processType="Private">
<bpmn2:extensionElements>
<tns:import name="com.summer.my.droolsproject.Fact.PersonFact"/>
</bpmn2:extensionElements>
<bpmn2:startEvent id="StartEvent_1" name="StartProcess">
<bpmn2:extensionElements>
<tns:metaData name="elementname">
<tns:metaValue><![CDATA[StartProcess]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
<bpmn2:outgoing>SequenceFlow_5</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:businessRuleTask id="BusinessRuleTask_2" tns:ruleFlowGroup="age-check-group" name="年龄校验">
<bpmn2:extensionElements>
<tns:metaData name="elementname">
<tns:metaValue><![CDATA[年龄校验]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
<bpmn2:incoming>SequenceFlow_5</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_8</bpmn2:outgoing>
</bpmn2:businessRuleTask>
<bpmn2:sequenceFlow id="SequenceFlow_5" tns:priority="1" sourceRef="StartEvent_1" targetRef="BusinessRuleTask_2"/>
<bpmn2:exclusiveGateway id="ExclusiveGateway_2" name="Exclusive Gateway 2" gatewayDirection="Diverging">
<bpmn2:incoming>SequenceFlow_8</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_9</bpmn2:outgoing>
<bpmn2:outgoing>SequenceFlow_10</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:sequenceFlow id="SequenceFlow_8" tns:priority="1" sourceRef="BusinessRuleTask_2" targetRef="ExclusiveGateway_2"/>
<bpmn2:businessRuleTask id="BusinessRuleTask_3" tns:ruleFlowGroup="teenager" name="child">
<bpmn2:extensionElements>
<tns:metaData name="elementname">
<tns:metaValue><![CDATA[child]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
<bpmn2:incoming>SequenceFlow_9</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_11</bpmn2:outgoing>
</bpmn2:businessRuleTask>
<bpmn2:sequenceFlow id="SequenceFlow_9" tns:priority="1" sourceRef="ExclusiveGateway_2" targetRef="BusinessRuleTask_3">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression" id="FormalExpression_1" language="http://www.jboss.org/drools/rule">p:PersonFact(age<=18)</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:businessRuleTask id="BusinessRuleTask_4" tns:ruleFlowGroup="adult" name="adult">
<bpmn2:extensionElements>
<tns:metaData name="elementname">
<tns:metaValue><![CDATA[adult]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
<bpmn2:incoming>SequenceFlow_10</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_12</bpmn2:outgoing>
</bpmn2:businessRuleTask>
<bpmn2:sequenceFlow id="SequenceFlow_10" tns:priority="2" sourceRef="ExclusiveGateway_2" targetRef="BusinessRuleTask_4">
<bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression" id="FormalExpression_2" language="http://www.jboss.org/drools/rule">eval(true)</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
<bpmn2:endEvent id="EndEvent_3" name="End Event 3">
<bpmn2:extensionElements>
<tns:metaData name="elementname">
<tns:metaValue><![CDATA[End Event 3]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
<bpmn2:incoming>SequenceFlow_11</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="SequenceFlow_11" tns:priority="1" sourceRef="BusinessRuleTask_3" targetRef="EndEvent_3"/>
<bpmn2:endEvent id="EndEvent_4" name="End Event 4">
<bpmn2:extensionElements>
<tns:metaData name="elementname">
<tns:metaValue><![CDATA[End Event 4]]></tns:metaValue>
</tns:metaData>
</bpmn2:extensionElements>
<bpmn2:incoming>SequenceFlow_12</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="SequenceFlow_12" tns:priority="1" sourceRef="BusinessRuleTask_4" targetRef="EndEvent_4"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_Process_1" bpmnElement="process.myProcess">
<bpmndi:BPMNShape id="BPMNShape_StartEvent_1" bpmnElement="StartEvent_1">
<dc:Bounds height="0.0" width="0.0" x="45.0" y="45.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="15.0" width="71.0" x="28.0" y="81.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_BusinessRuleTask_2" bpmnElement="BusinessRuleTask_2">
<dc:Bounds height="50.0" width="110.0" x="186.0" y="38.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="15.0" width="48.0" x="217.0" y="55.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_ExclusiveGateway_2" bpmnElement="ExclusiveGateway_2" isMarkerVisible="true">
<dc:Bounds height="50.0" width="50.0" x="371.0" y="38.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="30.0" width="57.0" x="368.0" y="88.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_BusinessRuleTask_3" bpmnElement="BusinessRuleTask_3">
<dc:Bounds height="50.0" width="110.0" x="526.0" y="38.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="15.0" width="26.0" x="568.0" y="55.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_BusinessRuleTask_4" bpmnElement="BusinessRuleTask_4">
<dc:Bounds height="50.0" width="110.0" x="526.0" y="138.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="15.0" width="27.0" x="567.0" y="155.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_EndEvent_3" bpmnElement="EndEvent_3">
<dc:Bounds height="36.0" width="36.0" x="704.0" y="45.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="15.0" width="65.0" x="690.0" y="81.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_EndEvent_4" bpmnElement="EndEvent_4">
<dc:Bounds height="36.0" width="36.0" x="704.0" y="145.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="15.0" width="65.0" x="690.0" y="181.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_5" bpmnElement="SequenceFlow_5" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_BusinessRuleTask_2">
<di:waypoint xsi:type="dc:Point" x="81.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="133.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="186.0" y="63.0"/>
<bpmndi:BPMNLabel/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_8" bpmnElement="SequenceFlow_8" sourceElement="BPMNShape_BusinessRuleTask_2" targetElement="BPMNShape_ExclusiveGateway_2">
<di:waypoint xsi:type="dc:Point" x="296.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="333.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="371.0" y="63.0"/>
<bpmndi:BPMNLabel/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_9" bpmnElement="SequenceFlow_9" sourceElement="BPMNShape_ExclusiveGateway_2" targetElement="BPMNShape_BusinessRuleTask_3">
<di:waypoint xsi:type="dc:Point" x="421.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="473.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="526.0" y="63.0"/>
<bpmndi:BPMNLabel/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_10" bpmnElement="SequenceFlow_10" sourceElement="BPMNShape_ExclusiveGateway_2" targetElement="BPMNShape_BusinessRuleTask_4">
<di:waypoint xsi:type="dc:Point" x="396.0" y="88.0"/>
<di:waypoint xsi:type="dc:Point" x="396.0" y="163.0"/>
<di:waypoint xsi:type="dc:Point" x="526.0" y="163.0"/>
<bpmndi:BPMNLabel/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_11" bpmnElement="SequenceFlow_11" sourceElement="BPMNShape_BusinessRuleTask_3" targetElement="BPMNShape_EndEvent_3">
<di:waypoint xsi:type="dc:Point" x="636.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="670.0" y="63.0"/>
<di:waypoint xsi:type="dc:Point" x="704.0" y="63.0"/>
<bpmndi:BPMNLabel/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_12" bpmnElement="SequenceFlow_12" sourceElement="BPMNShape_BusinessRuleTask_4" targetElement="BPMNShape_EndEvent_4">
<di:waypoint xsi:type="dc:Point" x="636.0" y="163.0"/>
<di:waypoint xsi:type="dc:Point" x="670.0" y="163.0"/>
<di:waypoint xsi:type="dc:Point" x="704.0" y="163.0"/>
<bpmndi:BPMNLabel/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>
PersonFact
package com.summer.my.droolsproject.Fact;
import java.util.Date;
public class PersonFact {
private String name;
private Integer age;
private Date birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}