Drools开源业务规则引擎(六)- Drools Flow中RuleFlow文件即*.rf文件介绍

发布于:2024-07-11 ⋅ 阅读:(17) ⋅ 点赞:(0)

Drools开源业务规则引擎(六)- RuleFlow文件即*.rf文件介绍

Drools Flow简介:

​ Drools 4.0有一个简单的“RuleFlow”功能,用于编排规则。Drools 5.0引入了一个强大的(可扩展的)工作流引擎。它允许用户使用规则和流程来指定他们的业务逻辑(在流程和规则之间可以进行强大的交互),并提供一个统一的环境。

​ 从Drools5.2版本起,Drools Flow项目和jBPM项目已合并到jBPM项目中,称为jBPM5(官方文档地址:https://docs.jboss.org/jbpm/v5.0/userguide)。jBPM 5.0已经发布,Drools项目将使用jBPM5作为引擎来支持流程功能。Drools Flow作为一个子项目将不再存在,但其愿景将继续作为jBPM项目的一部分,仍然允许(可选但)业务规则、业务流程和复杂事件处理之间的高级集成以及所有三种范式的统一环境。

​ *.rf文件可以说是在Drools6.4版本之前的规则流文件,Drools6.4及之后的版本中 *.rf 是已经淘汰了,但功能和bpmn2是一样的。由于 *.rf文件在可读性上比bpmn2要强一些,所以本文会先从简单的rf文件入手,以便大家方便理解《Drools开源业务规则引擎(五)- jBPM流程图元素介绍》,同时,一些简单的流程也可以通过rf文件去实现,并且不需要可视化工具,也可以手搓代码。

1.<header>

<header> 元素用来定义流程文件的元数据信息。

子标签/元素

  • <imports>:导入外部的类和包。可以使用这些导入的类和包来定义规则和行为。

  • <globals>:定义全局变量,这些变量在整个流程中均可使用。

  • <variables>:定义自定义属性,并在流程中进行配置和使用。

  • <functionImports>:定义自定义的函数。

  • <exceptionHandlers>:用于定义处理流程中发生的异常情况的异常处理程序。

1.1.<imports>

a.标签格式
  <xs:element name="imports">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:import"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
	<!-- 导入的import -->	
  <xs:element name="import">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • name:导入外部的类和包名。
c.示例代码
<header>
  <imports>
    <import name="com.ahao.project.input.UserIn"/>
  </imports>
</header>

1.2.<globals>

a.标签格式
<xs:element name="globals">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="drools:global"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
<xs:element name="global">
  <xs:complexType>
    <xs:attribute name="identifier" type="xs:string" use="required"/>
    <xs:attribute name="type" type="xs:string" use="required"/>
  </xs:complexType>
</xs:element>
b.属性说明
  • identifier:全局变量的标识符(名称)。
  • type:全局变量的类型。
c.示例代码
 <header>
    <globals>
      <global identifier="output" type="com.ahao.project.output.UserOut"/>
    </globals>
  </header>

1.3.<functionImports>

a.标签格式
<xs:element name="functionImports">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:functionImport"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="functionImport">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • name:带类型的函数名称。
c.示例代码
  <functionImports>
    <functionImport name="com.ahao.project.util.StrUtil.stringPrint"/>
  </functionImports>

1.4.<variables>

a.标签格式
  <!-- 对应类型:org.jbpm.process.core.context.variable.Variable -->
  <xs:element name="variables">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:variable"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="variable">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:type"/>
        <xs:element ref="drools:value"/>
      </xs:choice>
      <xs:attribute name="name" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="type">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string" use="required"/>
      <xs:attribute name="className" type="xs:string" />
    </xs:complexType>
  </xs:element>
  <xs:element name="value">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string"/>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
b.属性说明
  • name:变量名称。
    • type:变量类型。
      • name:类型的全路径类名(org.jbpm.process.core.datatype.impl.type包下)。
      • className:类名。
    • value:变量值。
c.示例代码
		<variables>
      <variable name="str">
        <type name="org.jbpm.process.core.datatype.impl.type.StringDataType" className="String"/>
        <value>测试内容</value>
      </variable>
    </variables>

1.5.<exceptionHandlers>

a.标签格式
  <!-- 对应类型:org.jbpm.compiler.xml.processes.ExceptionHandlerHandler -->
  <xs:element name="exceptionHandler">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:action"/>
      </xs:sequence>
      <xs:attribute name="faultName" type="xs:string" use="required"/>
      <xs:attribute name="type" type="xs:string" use="required"/>
      <xs:attribute name="faultVariable" type="xs:string"/>
    </xs:complexType>
  </xs:element>
	<!-- org.jbpm.workflow.core.node.ActionNode -->
  <xs:element name="action">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="name" type="xs:string"/>
          <xs:attribute name="type" type="xs:string"/>
          <xs:attribute name="dialect" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
b.属性说明
  • faultName:要处理的异常的类型或名称。
  • type:ExceptionHandler类型。
    • 可选值:action。
  • faultVariable:可选的变量名称,用来存储异常对象的引用。
  • exceptionHandler:定义了处理Java.lang.Exception类型异常的处理逻辑。
c.示例代码
  <header>
	  <exceptionHandlers>
      <exceptionHandler faultName="java.lang.NullPointerException" type="action">
        <action dialect="java" type="expression">
          System.out.println("+++++++异常了+++++++++");
        </action>
      </exceptionHandler>
    </exceptionHandlers>
  </header>

可以在流程中加入以下action节点,所抛出的异常会被上面的异常处理器捕获

Integer i = null; System.out.println("-----流程节点123-------"); System.out.println(i.toString());

在这里插入图片描述

2.<nodes>

规则流(RuleFlow)文件中定义节点的元素。节点表示流程中的一个步骤或活动,可以是任务、决策点、子流程等等。

公共属性

  • id:指定节点的唯一标识符。
  • name:指定节点的名称。
  • xy:指定节点在画布上的位置。
  • widthheight:指定节点的宽度和高度。

以上是节点的公共属性,后续小节将不会再过多说明。

子标签

<xs:element ref="drools:start"/>
<xs:element ref="drools:end"/>
<xs:element ref="drools:actionNode"/>
<xs:element ref="drools:ruleSet"/>
<xs:element ref="drools:split"/>
<xs:element ref="drools:join"/>
<xs:element ref="drools:milestone"/>
<xs:element ref="drools:subProcess"/>
<xs:element ref="drools:workItem"/>
<xs:element ref="drools:timerNode"/>
<xs:element ref="drools:humanTask"/>
<xs:element ref="drools:composite"/>
<xs:element ref="drools:forEach"/>
<xs:element ref="drools:eventNode"/>
<xs:element ref="drools:fault"/>
<xs:element ref="drools:state"/>
<xs:element ref="drools:dynamic"/>

2.1.<start>/<end>

<start>表示规则流的起点节点,<end>表示规则流的结束节点。

a.标签格式
  <!-- 起始节点 -->
  <xs:element name="start">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:metaData"/>
        <xs:element ref="drools:triggers"/>
      </xs:choice>
      <xs:attribute name="id" type="xs:string" use="required"/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="x" type="xs:string"/>
      <xs:attribute name="y" type="xs:string"/>
      <xs:attribute name="width" type="xs:string"/>
      <xs:attribute name="height" type="xs:string"/>
    </xs:complexType>
  </xs:element>
  <!-- 结束节点 -->
	<xs:element name="end">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:metaData"/>
      </xs:choice>
      <xs:attribute name="id" type="xs:string" use="required"/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="x" type="xs:string"/>
      <xs:attribute name="y" type="xs:string"/>
      <xs:attribute name="width" type="xs:string"/>
      <xs:attribute name="height" type="xs:string"/>
      <xs:attribute name="terminate" type="xs:string"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • <nodes>公共属性。
c.示例代码
<nodes>
    <start id="1" name="Start"  height="40"/>
  	<end id="4" name="End" x="372" y="77" width="80" height="40" />
</nodes>

2.2.<metaData>

在规则引擎中用于为规则和规则流(RuleFlow)等元素定义和存储元数据。元数据是与规则和规则流相关的附加信息,可以帮助规则引擎对规则进行管理、优化和执行。

元数据可以包含各种类型的信息,例如规则的作者、版本号、创建日期、规则状态等等。这些信息可以用于文档生成、规则管理、规则版本控制、规则访问控制或其他目的。

a.标签格式
  <xs:element name="metaData">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="1">
        <xs:element ref="drools:value"/>
      </xs:choice>
      <xs:attribute name="name" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • name:名称。
  • value:值。
c.示例代码
<nodes>
    <start id="1" name="Start"  height="40" >
      <metaData name="author">
        <value>AHAO</value>
      </metaData>
    </start>
</nodes>

2.3.<triggers>

触发器,用来在特定条件下触发某个节点的条件或事件。

a.标签格式
  <!-- 对应类型:org.jbpm.compiler.xml.processes.TriggerHandler -->
	<xs:element name="triggers">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:trigger"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <xs:element name="trigger">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:constraint"/>
        <xs:element ref="drools:eventFilters"/>
        <xs:element ref="drools:mapping"/>
      </xs:choice>
      <xs:attribute name="type" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • type:触发器类型。
    • 可选值:constraint,event。
c.示例代码
<triggers>
   <trigger type="constraint">
     <constraint dialect="mvel" type="rule" priority="1">
       UserIn(age > 10)
     </constraint>
   </trigger>
</triggers>

2.4.<constraint>

用于在规则引擎中定义规则条件。它指定了规则的条件表达式,只有当条件满足时,规则引擎才会执行该规则所定义的动作。

a.标签格式
  <xs:element name="constraint">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="toNodeId" type="xs:string"/>
          <xs:attribute name="toType" type="xs:string"/>
          <xs:attribute name="name" type="xs:string"/>
          <xs:attribute name="priority" type="xs:string"/>
          <xs:attribute name="type" type="xs:string"/>
          <xs:attribute name="dialect" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
b.属性说明
  • toNodeId:在条件满足时要执行的目标节点。
  • toType:目标类型。
  • name:名称。
  • priority:优先级。
  • type:指定条件类型。
    • 可选值:rule,code。
  • dialect:语义。
    • 可选值:mvel,java,JavaScript。
c.示例代码
<!-- rule mvel -->
<constraint type="rule" dialect="mvel" priority="1">
   UserIn(age > 10)
</constraint>

<!-- code java -->
return person.getAge() > 20;
<!-- code mvel -->
return person.age > 20;
<!-- code JavaScript -->
person.age > 20

2.5.<eventFilter>

过滤事件的类型,只有满足特定事件类型的事件才能在规则流中进行处理。对应org.jbpm.process.core.event.EventTypeFilter 类型。

a.标签格式
  <xs:element name="eventFilters">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:eventFilter"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="eventFilter">
    <xs:complexType>
      <xs:attribute name="type" type="xs:string" use="required"/>
      <xs:attribute name="eventType" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • type:事件过滤类型。
    • 可选值:eventType。
  • eventType:事件类型。
c.示例代码
<eventFilters>
  <eventFilter type="eventType" eventType="MyEventType"/>
</eventFilters>

2.6.<actionNode>

执行某种特定行为或操作的行为节点。

a.标签格式
  <xs:element name="actionNode">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:metaData"/>
        <xs:element ref="drools:action"/>
      </xs:choice>
      <xs:attribute name="id" type="xs:string" use="required"/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="x" type="xs:string"/>
      <xs:attribute name="y" type="xs:string"/>
      <xs:attribute name="width" type="xs:string"/>
      <xs:attribute name="height" type="xs:string"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="action">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="name" type="xs:string"/>
          <xs:attribute name="type" type="xs:string"/>
          <xs:attribute name="dialect" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
b.属性说明
  • name:名称。
  • type:行为类型。
    • 可选值:expression。
  • dialect:语义。
    • 可选值:java,mvel。
c.示例代码
<actionNode id="12">
<!--      <action type="expression" dialect="java" name="行为节点">-->
<!--        System.out.println("行为节点-全局变量[java]:"+output.getAgeStages());-->
<!--      </action>-->
   <action type="expression" dialect="mvel" name="行为节点">
     System.out.println("行为节点-全局变量[mvel]:"+output.ageStages);
   </action>
</actionNode>

2.7.<ruleSet>

规则集,表示一组相关的规则的集合。

a.标签格式
<xs:element name="ruleSet">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:metaData"/>
        <xs:element ref="drools:timers"/>
      </xs:choice>
      <xs:attribute name="id" type="xs:string" use="required"/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="x" type="xs:string"/>
      <xs:attribute name="y" type="xs:string"/>
      <xs:attribute name="width" type="xs:string"/>
      <xs:attribute name="height" type="xs:string"/>
      <xs:attribute name="ruleFlowGroup" type="xs:string"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • ruleFlowGroup:规则流分组,对应于drl文件中的ruleflow-group属性。
c.示例代码
<ruleSet id="2" name="规则流分组1" ruleFlowGroup="Group1">
</ruleSet>

2.8.<split>

分支节点,用于创建分支,将规则流的执行流程拆分成多个并行的分支(相当于网关)。

a.标签格式
<xs:element name="split">
  <xs:complexType>
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="drools:metaData"/>
      <xs:element ref="drools:constraints"/>
    </xs:choice>
    <xs:attribute name="id" type="xs:string" use="required"/>
    <xs:attribute name="name" type="xs:string"/>
    <xs:attribute name="x" type="xs:string"/>
    <xs:attribute name="y" type="xs:string"/>
    <xs:attribute name="width" type="xs:string"/>
    <xs:attribute name="height" type="xs:string"/>
    <xs:attribute name="type" type="xs:string"/>
  </xs:complexType>
</xs:element>
b.属性说明
  • type:以下是可选类型。(org.jbpm.workflow.core.node.Split)。
    • 0:TYPE_UNDEFINED。未定义类型
    • 1:TYPE_AND。所有的分支路径都必须满足条件,才能够通过分裂节点。
    • 2:TYPE_XOR。只有一个分支路径能够满足条件,才能够通过分裂节点。
    • 3:TYPE_OR。至少有一个分支路径能够满足条件,就可以通过分裂节点。
c.示例代码
<split id="123" type="2">
   <constraints>
      <constraint toNodeId="2" type="rule" dialect="mvel">
        UserIn(age &lt;= 10)
      </constraint>
      <constraint toNodeId="3" type="rule" dialect="mvel">
        UserIn(age > 10)
      </constraint>
   </constraints>
</split>

2.9.<join>

合并节点,用于定义流程的合并行为。(相当于合并网关,配合<split>标签一起使用)

a.标签格式
  <xs:element name="join">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:metaData"/>
      </xs:choice>
      <xs:attribute name="id" type="xs:string" use="required"/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="x" type="xs:string"/>
      <xs:attribute name="y" type="xs:string"/>
      <xs:attribute name="width" type="xs:string"/>
      <xs:attribute name="height" type="xs:string"/>
      <xs:attribute name="type" type="xs:string"/>
      <xs:attribute name="n" type="xs:string"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • type:以下是可选类型。(org.jbpm.workflow.core.node.Join)。
    • 0:TYPE_UNDEFINED。未定义类型
    • 1:TYPE_AND。合并节点要求所有传入的分支都执行完毕后,才能够继续执行合并节点之后的操作。
    • 2:TYPE_XOR。只有一个分支路径能够满足条件,才能够执行合并节点之后的操作。
    • 3:TYPE_DISCRIMINATOR。只有一个分支路径能够满足条件,才能够执行合并节点之后的操作。
    • 4:TYPE_N_OF_M。至少有n个分支路径能够满足条件,才能够执行合并节点之后的操作。
    • 5:TYPE_OR。至少有一个分支路径能够满足条件,才能够执行合并节点之后的操作。
  • n:满足条件分支数量。(当类型为TYPE_N_OF_M生效)
c.示例代码
<join id="1234" type="5"></join>

2.10.<timerNode>

定时器节点,在指定的时间点或时间间隔执行后续操作。

a.标签格式
  <xs:element name="timerNode">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:metaData"/>
      </xs:choice>
      <xs:attribute name="id" type="xs:string" use="required"/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="x" type="xs:string"/>
      <xs:attribute name="y" type="xs:string"/>
      <xs:attribute name="width" type="xs:string"/>
      <xs:attribute name="height" type="xs:string"/>
      <xs:attribute name="delay" type="xs:string"/>
      <xs:attribute name="period" type="xs:string"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • delay:延迟时间
  • period:循环周期
c.示例代码
<timerNode id="5" delay="1s" period="1d"/>

2.11.<eventNodeNode>

事件节点需要指定节点感兴趣的事件类型。它还可以定义变量的名称,该变量将接收与该事件相关联的数据。这允许流程中的后续节点访问事件数据,并根据这些数据采取适当的操作。

a.标签格式
<xs:element name="eventNode">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="drools:metaData"/>
        <xs:element ref="drools:eventFilters"/>
      </xs:choice>
      <xs:attribute name="id" type="xs:string" use="required"/>
      <xs:attribute name="name" type="xs:string"/>
      <xs:attribute name="x" type="xs:string"/>
      <xs:attribute name="y" type="xs:string"/>
      <xs:attribute name="width" type="xs:string"/>
      <xs:attribute name="height" type="xs:string"/>
      <xs:attribute name="variableName" type="xs:string"/>
      <xs:attribute name="scope" type="xs:string"/>
    </xs:complexType>
  </xs:element>
b.属性说明
  • variableName:变量名称

  • scope:发送事件信号的方式

    • Internal:内部

      • kcontext.getProcessInstance().signalEvent(type, eventData);
        
    • external:外部

      • ksession.signalEvent(type, eventData);
        
c.示例代码
 <eventNode id="61" variableName="str" scope="external">
    <eventFilters>
        <eventFilter type="eventType" eventType="myEvent"/>
    </eventFilters>
 </eventNode>
<!--
	kieSession.signalEvent("myEvent","Singal Event");
-->

3.<connections>

用于定义规则流中不同节点之间的连接关系。在规则引擎中,规则流可以被看作是一系列规则节点的有向图,并且节点之间的连接定义了规则执行的先后顺序。 <connections> 元素应该包含一个或多个 <connection> 子元素,每个 <connection> 元素定义了两个节点之间的连接。

标签格式

<xs:element name="connections">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="drools:connection"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
<xs:element name="connection">
  <xs:complexType>
    <xs:attribute name="from" type="xs:string" use="required"/>
    <xs:attribute name="to" type="xs:string" use="required"/>
    <xs:attribute name="fromType" type="xs:string"/>
    <xs:attribute name="toType" type="xs:string"/>
    <xs:attribute name="bendpoints" type="xs:string"/>
  </xs:complexType>
</xs:element>

属性说明

  • from:连接的起始节点(id)。
  • to:连接的目标节点(id)。
  • fromType:表示起始节点的类型。
  • toType:表示目标节点的类型。
  • bendpoints:连接的弯曲点。

示例代码

  <nodes>
    <start id="1" name="Start"  height="40" />
    <end id="2" name="End" height="40" />
  </nodes>
	<connections>
    <connection from="1" to="2" />
  </connections>

4.案例代码

4.1.依赖导入

        <dependency>
            <groupId>org.jbpm</groupId>
            <artifactId>jbpm-bpmn2</artifactId>
            <version>7.6.0.Final</version>
        </dependency>

4.2.规则文件(DRL)

package drools.ruleflow;
dialect  "mvel"

// 导入输入类型
import com.ahao.project.input.UserIn;
global com.ahao.project.output.UserOut output;


rule "group1"
ruleflow-group "Group1"
when
    $in:UserIn(age <= 10)
then
    output.setAgeStages("<=10");
end

rule "group2"
ruleflow-group "Group2"
when
    $in:UserIn()
then
    output.setAgeStages(">>>>>10");
end

4.3.规则流文件(DRF)

<?xml version="1.0" encoding="UTF-8"?>
<process xmlns="http://drools.org/drools-5.0/process"
         xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
         xs:schemaLocation="http://drools.org/drools-5.0/process drools-processes-5.0.xsd"
         type="RuleFlow" name="RuleFlow_Demo" id="RFDemo" package-name="drools.ruleflow">

    <header>
        <imports>
            <import name="com.ahao.project.input.UserIn"/>
            <import name="com.ahao.project.util.DateTimeUtil"/>
        </imports>
        <globals>
            <global identifier="output" type="com.ahao.project.output.UserOut"/>
        </globals>
        <variables>
            <variable name="str">
                <type name="org.jbpm.process.core.datatype.impl.type.StringDataType" className="String"/>
                <value>测试内容</value>
            </variable>
        </variables>
        <exceptionHandlers>
            <exceptionHandler faultName="java.lang.NullPointerException" type="action">
                <action dialect="java" type="expression">
                    System.out.println("+++++++异常了+++++++++");
                </action>
            </exceptionHandler>
        </exceptionHandlers>
    </header>

    <nodes>
        <start id="1" name="Start" height="40">
            <metaData name="TriggerMapping">
                <value>AHAO</value>
            </metaData>
            <triggers>
                <trigger type="event">
                    <eventFilters>
                        <eventFilter type="eventType" eventType="None"/>
                    </eventFilters>
                </trigger>
            </triggers>
        </start>
        <actionNode id="12">
            <!--      <action type="expression" dialect="java" name="行为节点">-->
            <!--        System.out.println("行为节点-全局变量[java]:"+output.getAgeStages());-->
            <!--      </action>-->
            <action type="expression" dialect="mvel" name="行为节点">
                System.out.println("行为节点-全局变量[mvel]:"+output.ageStages);
            </action>
        </actionNode>
        <split id="123" type="2">
            <constraints>
                <constraint toNodeId="2" type="rule" dialect="mvel">
                    UserIn(age &lt;= 10)
                </constraint>
                <constraint toNodeId="3" type="rule" dialect="mvel">
                    UserIn(age > 10)
                </constraint>
            </constraints>
        </split>
        <join id="1234" type="3"></join>
        <ruleSet id="2" name="Verify" x="162" y="77" width="80" height="40" ruleFlowGroup="Group1">
        </ruleSet>
        <ruleSet id="3" name="Calculation" x="267" y="77" width="80" height="40" ruleFlowGroup="Group2"/>
        <actionNode id="41">
            <!--      <action type="expression" dialect="java" name="行为节点">-->
            <!--        System.out.println("行为节点-全局变量[java]:"+output.getAgeStages());-->
            <!--      </action>-->
            <action type="expression" dialect="mvel" name="结束行为节点">
                System.out.println(DateTimeUtil.now()+": 结束行为!!!!!");
            </action>
        </actionNode>
        <eventNode id="61" variableName="str" scope="external">
            <eventFilters>
                <eventFilter type="eventType" eventType="None"/>
            </eventFilters>
        </eventNode>
        <timerNode id="5" delay="1s"/>
        <actionNode id="42">
            <!--      <action type="expression" dialect="java" name="行为节点">-->
            <!--        System.out.println("行为节点-全局变量[java]:"+output.getAgeStages());-->
            <!--      </action>-->
            <action type="expression" dialect="mvel" name="结束前行为节点">
                System.out.println(DateTimeUtil.now()+": 结束前!!!!");
            </action>
        </actionNode>
        <end id="4" name="End" x="372" y="77" width="80" height="40"/>
    </nodes>

    <connections>
        <connection from="1" to="12"/>
        <connection from="12" to="123"/>
        <connection from="123" to="2"/>
        <connection from="123" to="3"/>
        <connection from="2" to="1234"/>
        <connection from="3" to="1234"/>
        <connection from="1234" to="41"/>
        <connection from="41" to="61"/>
        <connection from="61" to="5"/>
        <connection from="5" to="42"/>
        <connection from="42" to="4"/>
    </connections>

</process>

4.4.测试方法

    @Test
    public void test() throws InterruptedException {
      	// 获取文件内容
        String drl = ResourceUtil.fileContent("classpath:drools/ruleflow/rule-flow.drl");
        String rf = ResourceUtil.fileContent("classpath:drools/ruleflow/RuleFlowDemo.rf");
        KieHelper kieHelper = new KieHelper();
        KieBaseConfiguration kieBaseConfiguration = kieHelper.ks.newKieBaseConfiguration();
      	// 加入文件内容,以便编译文件
        kieHelper.addContent(drl, ResourceType.DRL);
        kieHelper.addContent(rf,ResourceType.DRF);
        KieBase kieBase = kieHelper.build(kieBaseConfiguration);
        KieSession kieSession = kieBase.newKieSession();
        // 创建规则输出对象
        UserOut output = new UserOut();
        kieSession.setGlobal("output", output);
        // 创建规则输入对象
        UserIn input = new UserIn();
        input.setAge(19);
        // 执行规则
        kieSession.insert(input);
        // 指定流程id
        kieSession.startProcess("RFDemo");
        kieSession.fireAllRules();
        // 触发事件
        kieSession.signalEvent("None","2");
        kieSession.signalEvent("None","2");
    }