背景
现在需要有一个节点,需要在流程到达这个节点的时候,需要将当前流程表单的一些参数作为参数调用外部的http地址,如果这个地址返回了成功,那么这个节点就继续往下走。
分析
按照上面的需求,我们需要做的主要是以下功能
- 入参,勾选表单的参数
- 调用地址
- 调用方式(GET\POST)
- 返回值判断(外部接口按照我们的定义统一返回就行)
- 异常处理
- 邮件
- 企业微信告警
实现
前端部分
用的是bpmn.js的插件,需要自定义属性,最终展示效果为:
流程编辑页
设置完右侧的属性之后,我们这个节点的属性就设置完毕了。
最终提交的xml类似于下面这种:
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:activiti="http://activiti.org/bpmn" id="m1577635100724" name="" targetNamespace="http://www.activiti.org/testm1577635100724">
<process id="process1620637878536" processType="None" isClosed="false" isExecutable="true">
<extensionElements>
<activiti:properties>
<activiti:property name="a" value="1" />
</activiti:properties>
</extensionElements>
<startEvent id="_2" name="开始">
<outgoing>Flow_0ca559g</outgoing>
</startEvent>
<sequenceFlow id="Flow_0ca559g" sourceRef="_2" targetRef="submitTask" />
<userTask id="submitTask" name="提交节点" activiti:assignType="variable" activiti:assignValue="submitUser">
<incoming>Flow_0ca559g</incoming>
<outgoing>Flow_0a6iosp</outgoing>
</userTask>
<sequenceFlow id="Flow_0a6iosp" sourceRef="submitTask" targetRef="Activity_03v64y1" />
<serviceTask id="Activity_03v64y1" name="自动化呀" activiti:class="com.*.interceptor.listener.ServiceTaskAuto" activiti:action="POST" activiti:url="http://test.com" activiti:forms="input_1619676303000_42933,input_1619676304000_57954,date_1619676335000_46739" activiti:abnormalWarning="email" activiti:email="chenquanwei@keytop.com.cn" activiti:wxwork="">
<incoming>Flow_0a6iosp</incoming>
<outgoing>Flow_01wlhjl</outgoing>
</serviceTask>
<exclusiveGateway id="Gateway_19nsa55">
<incoming>Flow_01wlhjl</incoming>
<outgoing>Flow_021bick</outgoing>
<outgoing>Flow_1rt8i2h</outgoing>
</exclusiveGateway>
<sequenceFlow id="Flow_01wlhjl" sourceRef="Activity_03v64y1" targetRef="Gateway_19nsa55" />
<sequenceFlow id="Flow_021bick" name="成功" sourceRef="Gateway_19nsa55" targetRef="Activity_1c2dbe5" activiti:condition="${approvalAuto==true}" />
<sequenceFlow id="Flow_1rt8i2h" name="失败" sourceRef="Gateway_19nsa55" targetRef="Activity_1qq721y" activiti:condition="${approvalAuto==false}" />
<userTask id="Activity_1c2dbe5" name="自动化成" activiti:assignType="role" activiti:assignValue="1">
<incoming>Flow_021bick</incoming>
<outgoing>Flow_1xurbpo</outgoing>
</userTask>
<userTask id="Activity_1qq721y" name="自动化败" activiti:assignType="person" activiti:assignValue="2,1">
<incoming>Flow_1rt8i2h</incoming>
<outgoing>Flow_162pjte</outgoing>
</userTask>
<sequenceFlow id="Flow_162pjte" sourceRef="Activity_1qq721y" targetRef="Event_151mw34" />
<sequenceFlow id="Flow_1xurbpo" sourceRef="Activity_1c2dbe5" targetRef="Event_151mw34" />
<endEvent id="Event_151mw34">
<incoming>Flow_162pjte</incoming>
<incoming>Flow_1xurbpo</incoming>
</endEvent>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_leave">
<bpmndi:BPMNPlane id="BPMNPlane_leave" bpmnElement="process1620637878536">
<bpmndi:BPMNEdge id="Flow_0ca559g_di" bpmnElement="Flow_0ca559g">
<di:waypoint x="176" y="384" />
<di:waypoint x="230" y="384" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0a6iosp_di" bpmnElement="Flow_0a6iosp">
<di:waypoint x="330" y="384" />
<di:waypoint x="390" y="384" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_01wlhjl_di" bpmnElement="Flow_01wlhjl">
<di:waypoint x="490" y="384" />
<di:waypoint x="555" y="384" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_021bick_di" bpmnElement="Flow_021bick">
<di:waypoint x="580" y="359" />
<di:waypoint x="580" y="290" />
<di:waypoint x="670" y="290" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="585" y="322" width="21" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1rt8i2h_di" bpmnElement="Flow_1rt8i2h">
<di:waypoint x="580" y="409" />
<di:waypoint x="580" y="500" />
<di:waypoint x="670" y="500" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="584" y="452" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_162pjte_di" bpmnElement="Flow_162pjte">
<di:waypoint x="770" y="500" />
<di:waypoint x="816" y="500" />
<di:waypoint x="816" y="400" />
<di:waypoint x="862" y="400" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1xurbpo_di" bpmnElement="Flow_1xurbpo">
<di:waypoint x="770" y="290" />
<di:waypoint x="816" y="290" />
<di:waypoint x="816" y="400" />
<di:waypoint x="862" y="400" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="BPMNShape__2" bpmnElement="_2">
<omgdc:Bounds x="144" y="368" width="32" height="32" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="149" y="400" width="23" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1pxs7ok_di" bpmnElement="submitTask">
<omgdc:Bounds x="230" y="344" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1ipcnqz_di" bpmnElement="Activity_03v64y1">
<omgdc:Bounds x="390" y="344" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_19nsa55_di" bpmnElement="Gateway_19nsa55" isMarkerVisible="true">
<omgdc:Bounds x="555" y="359" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_12asdev_di" bpmnElement="Activity_1c2dbe5">
<omgdc:Bounds x="670" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0tlrnwu_di" bpmnElement="Activity_1qq721y">
<omgdc:Bounds x="670" y="460" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0oq8k35_di" bpmnElement="Event_151mw34">
<omgdc:Bounds x="862" y="382" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
后端部分
因为都是自定义属性,所以我们需要写一个转化类的代码
部署转化类代码:
public class CustomServiceTaskXMLConverter extends ServiceTaskXMLConverter {
@Override
protected BaseElement convertXMLToElement(XMLStreamReader xtr, BpmnModel model) throws Exception {
ServiceTask serviceTask = new ServiceTask();
// 省略一些代码
// 设置自定义属性到customProperties
List<CustomProperty> customProperties = new ArrayList<>();
ActivitiConstants.SERVICE_TASK_ATTRS[] values = ActivitiConstants.SERVICE_TASK_ATTRS.values();
for ( ActivitiConstants.SERVICE_TASK_ATTRS serviceTaskAttrs : values ) {
String attributeValue = xtr.getAttributeValue(null, serviceTaskAttrs.getAttrName());
if (StringUtils.isNotEmpty(attributeValue)) {
CustomProperty customProperty = new CustomProperty();
customProperty.setId(serviceTaskAttrs.getAttrName());
customProperty.setName(serviceTaskAttrs.getAttrName());
customProperty.setSimpleValue(attributeValue);
customProperties.add(customProperty);
}
}
serviceTask.setCustomProperties(customProperties);
// 省略一些代码
return serviceTask;
}
}
部署转化bpmn的时候需要添加自定义的转化类BpmnXMLConverter.addConverter(new CustomServiceTaskXMLConverter());
监听类:
public class ServiceTaskAuto implements JavaDelegate {
/**
* 这里是每个自定义属性的字段名
*/
private FixedValue action;
@Override
public void execute(DelegateExecution execution) {
// 根据业务完成自己的校验动作
// 如果成功,设置流程属性,失败的话,设置失败的属性,让流程走向失败的节点
}
}
提交流程到了这个节点可以看到获取到的参数为:
流程执行参数
问题
-
com...interceptor.listener.ServiceTaskAuto org.activiti.engine.ActivitiIllegalArgumentException: Field definition uses unexisting field 'action' on class com...interceptor.listener.ServiceTaskAuto
这个是因为在监听器里接收的方式不对,我们的自定义属性都需要通过FixedValue来接收,并且我们设置的所有属性值,都必须在这边有接收的属性,一开始是采用下面的方式接收的,就会报这个错。
private Expression attrs; @Override public void execute(DelegateExecution execution) { }
未竟之事
- http当成一个策略,不止http调用外部,可以是mq发送
- 节点的校验,做的比较粗糙,还没有对一些属性进行校验
- 重试?接口调用在实现类重试还是serviceTask的重试









网友评论