Skip to content

协议详解

yusu1210 edited this page Oct 28, 2020 · 2 revisions

1 BPM根节点

1.1 协议

<bpm code="bpm.ktvExample" name="ktv example" type="process" description="ktv example">......</bpm>

1.2 说明

属性code: 该属性最重要,当引擎start执行流程时,会要求传入code参数,这个参数就是流程文件中的code字段。code约定用点表示文件存放目录层级。如上bpm.ktvExample表示文件在resources下的bpm文件夹下,名字叫ktvExample。

属性type: 目前固定写死process,后续可扩展支持多种类型流程。

属性name: 按自己工程需要命名。

属性description: 按自己工程需要命名。

引擎执行流程代码片段:

Map<String, Object> result = ProcessEngineFactory.getProcessEngine().start(code, context);

2 全局变量

2.1 协议

<var name="price" description="支付价格" dataType="java.lang.Integer" inOutType="return"></var>

2.2 说明

参数用var节点表示。直接在根节点bpm下的就叫全局参数。

inOutType属性: 表示参数类型,值有3种:param、inner、return。

param: 表示对应引擎start的入参。当我们start流程时,除了需要设置code,还需要设置context。他是一个MAP,其中key就需要映射成上面var节点的name属性。

inner: 表示内部运行时各个节点执行后的中间变量。

return: 表示返回结果变量。流程执行完成后,我们拿到了一个result结果。是个MAP。其中指定了return类型的var节点,我们可以通过name作为key从result拿到值。

dataType属性: 参数类型,支持java类型写法例如上面的:java.lang.Integer。

name属性: 变量名称

description属性: 变量描述

3 开始节点:start

3.1 协议

<start id="1" name="开始" tag="223" g="105,17,30,30">
    <transition to="13" g=":-15,20"></transition>
</start>

3.2 说明

流程的开始节点用start表示。其中transition表示指向下一个节点。to就是下一个节点的id。

id属性: 节点的唯一标志,请保持唯一

tag属性: 节点的附加数据

name属性: 节点名称会在流程图上显示

g属性: 目前不用关注,对绘制流程图有用,对流程的执行不影响

4 结束节点:end

4.1 协议

<end id="11" name="结束" tag="好的" g="101,549,30,30"></end>

4.2 说明

同上,唯一不同的是没有transition,因为结束节点表示流程的结束,不会再指向下一个节点了。

5 自动节点:autoTask

5.1 协议

<autoTask id="12" name="付款" g="72,469,88,48">
    <transition to="11" g=":-15,20"></transition>
    <action type="spring-bean">
      <actionHandle bean="mockSpringBean" clazz="com.alibaba.compileflow.demo.mock.MockSpringBean" method="payMoney">
        <var name="p1" description="价格" dataType="java.lang.Integer" contextVarName="price" inOutType="param"></var>
      </actionHandle>
    </action>
  </autoTask>

5.2 说明

自动节点用autoTask表示是最常见的。他主要执行一段逻辑。目前支持springBean的配置和普通javaBean的配置。其中action就是要配置的动作。下面actionHandle配置该动作出入参。最终这个节点会被编译成javaCode如下:

//AutoTaskNode: 付款
((MockSpringBean)BeanProvider.getBean("mockSpringBean")).payMoney(price);

6 判断节点:decision

6.1 协议

<decision id="8" name="计算费用" g="72,309,88,48">
    <transition to="9" priority="1" name="不超过300" g=":-15,20"></transition>
    <transition to="10" priority="2" name="超过300" expression="totalPrice&gt;=300" g=":-15,20"></transition>
    <action type="java">
      <actionHandle clazz="com.alibaba.compileflow.demo.mock.MockJavaClazz" method="calPrice">
        <var name="p1" description="人数" dataType="java.lang.Integer" contextVarName="pList.size()" inOutType="param"></var>
        <var name="p2" description="价格" dataType="java.lang.Integer" contextVarName="totalPrice" inOutType="return"></var>
      </actionHandle>
    </action>
  </decision>

6.2 说明

判断节点用decision表示。他主要执行一段逻辑。然后根据执行后的逻辑值进行表达式判断后,再走不同的分支。例如上面会先执行com.alibaba.compileflow.demo.mock.MockJavaClazz的calPrice方法。calPrice方法会返回p2变量。其中他的上下文名称是totalPrice。执行完成后,引擎会根据transition的expression表达式。进行逻辑选择,例如该节点会编译成javaCode:

private void decision8() {
        //DecisionNode: 计算费用
        mockJavaClazzCalPrice();
        if (totalPrice>=300) {
            //超过300
            {
                //ScriptTaskNode: 9折优惠
                IExpressContext<String, Object> nfScriptContext = new DefaultContext<>();
                nfScriptContext.put("price", totalPrice);
                price = (java.lang.Integer)ScriptExecutorProvider.getInstance().getScriptExecutor("QL").execute("(round(price*0.9,0)).intValue()", nfScriptContext);
            }
        } else {
            //不超过300
            {
                //ScriptTaskNode: 原价
                IExpressContext<String, Object> nfScriptContext = new DefaultContext<>();
                nfScriptContext.put("price", totalPrice);
                price = (java.lang.Integer)ScriptExecutorProvider.getInstance().getScriptExecutor("QL").execute("price*1", nfScriptContext);
            }
        }
    }

7 脚本节点:scriptTask

7.1 协议

<scriptTask id="9" name="原价" g="132,389,88,48">
    <transition to="12" g=":-15,20"></transition>
    <action type="ql">
      <actionHandle expression="price*1">
        <var name="price" description="价格" dataType="java.lang.Integer" contextVarName="totalPrice" inOutType="param"></var>
        <var name="price" description="价格" dataType="java.lang.Integer" contextVarName="price" inOutType="return"></var>
      </actionHandle>
    </action>
  </scriptTask>

7.2 说明

脚本节点和自动节点差不多含义。就是执行一段逻辑。只是自动节点可以执行一个springBean或者一个javaBean。而脚本节点指定的是一个表达式。目前支持QL表示环境执行。例如上面会编译成javaCode:

//ScriptTaskNode: 原价
IExpressContext<String, Object> nfScriptContext = new DefaultContext<>();
nfScriptContext.put("price", totalPrice);
price = (java.lang.Integer)ScriptExecutorProvider.getInstance().getScriptExecutor("QL").execute("price*1", nfScriptContext);

8 循环节点

8.1 协议

<loopProcess id="13" name="循环节点" collectionVarName="pList" variableName="p" indexVarName="i" variableClass="java.lang.String" startNodeId="13-1" endNodeId="13-1" g="20,75,198,190">
    <transition to="8" g=":-15,20"></transition>
    <autoTask id="13-1" name="每人唱一首歌" g="50,80,88,48">
      <action type="spring-bean">
        <actionHandle bean="mockSpringBean" clazz="com.alibaba.compileflow.demo.mock.MockSpringBean" method="sing">
          <var name="p1" dataType="java.lang.String" contextVarName="p" inOutType="param"></var>
        </actionHandle>
      </action>
    </autoTask>
  </loopProcess>

8.2 说明

循环节点的作用是,包裹部分流程进行循环执行。collectionVarName表示要循环的列表变量。variableName表示每个循环的局部变量。indexVarName表示循环的次数。如上面的协议会翻译下面的javaCode:

int i = -1;
for (String p : pList) {
    i++;
    //AutoTaskNode: 每人唱一首歌
    ((MockSpringBean)BeanProvider.getBean("mockSpringBean")).sing((String)DataType.transfer(p, String.class));
}