-
Notifications
You must be signed in to change notification settings - Fork 275
协议详解
<bpm code="bpm.ktvExample" name="ktv example" type="process" description="ktv example">......</bpm>
属性code: 该属性最重要,当引擎start执行流程时,会要求传入code参数,这个参数就是流程文件中的code字段。code约定用点表示文件存放目录层级。如上bpm.ktvExample表示文件在resources下的bpm文件夹下,名字叫ktvExample。
属性type: 目前固定写死process,后续可扩展支持多种类型流程。
属性name: 按自己工程需要命名。
属性description: 按自己工程需要命名。
引擎执行流程代码片段:
Map<String, Object> result = ProcessEngineFactory.getProcessEngine().start(code, context);
<var name="price" description="支付价格" dataType="java.lang.Integer" inOutType="return"></var>
参数用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属性: 变量描述
<start id="1" name="开始" tag="223" g="105,17,30,30">
<transition to="13" g=":-15,20"></transition>
</start>
流程的开始节点用start表示。其中transition表示指向下一个节点。to就是下一个节点的id。
id属性: 节点的唯一标志,请保持唯一
tag属性: 节点的附加数据
name属性: 节点名称会在流程图上显示
g属性: 目前不用关注,对绘制流程图有用,对流程的执行不影响
<end id="11" name="结束" tag="好的" g="101,549,30,30"></end>
同上,唯一不同的是没有transition,因为结束节点表示流程的结束,不会再指向下一个节点了。
<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>
自动节点用autoTask表示是最常见的。他主要执行一段逻辑。目前支持springBean的配置和普通javaBean的配置。其中action就是要配置的动作。下面actionHandle配置该动作出入参。最终这个节点会被编译成javaCode如下:
//AutoTaskNode: 付款
((MockSpringBean)BeanProvider.getBean("mockSpringBean")).payMoney(price);
<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>=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>
判断节点用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);
}
}
}
<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>
脚本节点和自动节点差不多含义。就是执行一段逻辑。只是自动节点可以执行一个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);
<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>
循环节点的作用是,包裹部分流程进行循环执行。collectionVarName表示要循环的列表变量。variableName表示每个循环的局部变量。indexVarName表示循环的次数。如上面的协议会翻译下面的javaCode:
int i = -1;
for (String p : pList) {
i++;
//AutoTaskNode: 每人唱一首歌
((MockSpringBean)BeanProvider.getBean("mockSpringBean")).sing((String)DataType.transfer(p, String.class));
}