工作流-camunda之场景应用

使用camunda作后端接口编排

我们在使用camnuda作为后端接口编排组件后,在实际开发应用中遇到了不少问题,在此做一些总结,供后期查阅

前端改造

camunda 官方提供了流程图绘制客户端,但是由于我们是B/S系统所以需要将流程设计器集成到网页端,于是我们使用vue3+ts结合bpmn.js做了对camunda属性面板改造,实现如下功能:

  1. vue3+ts+bpmn.js ,将camunda流程设计器集成到网页端;
  2. 使用bpmn2.0中的服务任务 + 网关 + 流转条件实现接口编排;
  3. 使用bpmn2.0中的事物子流程 + 边界异常事件 + 取消事件 + 补偿节点实现分布式事务控制;

后端驱动

使用camunda流程引擎api实现流程初始化,部署,实例启动等:

  1. 利用代理表达式 ,实现对流程设计器中配置的接口进行触发调用;
  2. 使用监听器实现流程返回结果处理;

代码实现 & 效果展示

首先前端引入bpmn.js依赖

npm i bpmn-js --save

引入camuda.json标准和国际化文件
在这里插入图片描述
编写modeler代码

import './modeler.css';
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
import 'diagram-js-minimap/assets/diagram-js-minimap.css'

import { defineComponent, onMounted } from 'vue';
import createDefaultBpmnXml from '../../../bpmn/defaultBpmnXml';
import camoundaModdel from '../../../bpmn/resources/camunda.json';
import translate from '../../../bpmn/i18n';
import { BpmnStore } from '../../../bpmn/store';
import minimapModule from 'diagram-js-minimap'

export default defineComponent({
  name: 'Modeler',
  setup() {
    const bpmnContext = BpmnStore;
    onMounted(() => {
      bpmnContext.initModeler({
        container: '#modeler-container',
        additionalModules: [
          //添加翻译
          { translate: ['value', translate('zh')] },
          //小地图
          minimapModule
        ],
        moddleExtensions: {
          camunda: camoundaModdel,
        },
      });
      const defaultProcessIdAndName = '1';
      bpmnContext
        .importXML(createDefaultBpmnXml(defaultProcessIdAndName, defaultProcessIdAndName))
        .then((result: Array<string>) => {
          if (result.length) {
            console.warn('importSuccess warnings', result);
          }
        })
        .catch((err: any) => {
          console.warn('importFail errors ', err);
        });
    });

    return () => <div id="modeler-container"/>;
  },
});

界面效果:
在这里插入图片描述
后端代理表达式代码

@Component("codeInterfaceHandler")
public class CodeInterfaceHandler implements JavaDelegate {

    @Resource
    private RestTemplate restTemplate;

    @Override
    public void execute(DelegateExecution execution) throws Exception {
        // 获取接口id
        String interfaceId = getInterfaceId(execution);
        // 根据接口id查询接口
        ServiceAssert.isNotNull(interfaceId, "未挂接接口id");
        String url = PROTOCOL + SysConstants.SERVICE_NAME + GET_INTERFACE_BY_ID_URL + interfaceId;
        ApiResult apiResult = restTemplate.getForObject(url, ApiResult.class);
        ServiceAssert.isNotNull(apiResult.getData(), apiResult.getMessage());
        SysInterface sysInterface = JSONUtil.toBean(JSONUtil.toJsonStr(apiResult.getData()), SysInterface.class);
        ServiceAssert.isNotNull(sysInterface, "接口信息不存在");
    }

}

后端监听器代码

@Component("codeFlowEndEventListener")
public class CodeFlowEndEventListener implements ExecutionListener {
    @Override
    public void notify(DelegateExecution execution) throws Exception {
        // 任务结束,组织返回数据
        Map result = new HashMap(16);
        execution.getVariablesLocal().forEach((k, v) -> {
            if (execution.getProcessInstance().getVariable(k) != null) {
                result.put(k, execution.getProcessInstance().getVariable(k));
            }
        });
        if (!CollectionUtil.isEmpty(result)) {
            execution.getProcessInstance().setVariable(CodeLogicalFlowConstants.RETURN_DATA_OF_FLOW, result);
        }
    }
}

流程驱动代码:

@Transactional(rollbackFor = Exception.class)
    public Map<String, Object> process(String flowCode, String json) {
        ServiceAssert.isTrue(StrUtil.isNotBlank(json), "未传入逻辑流程入参");
        Map<String, Object> paramMap = JSONUtil.parseObj(json);

        ProcessInstanceWithVariables processInstance;
        try {
            // 流程启动参数,是逻辑流程生成接口入参,将放入流程变量中
            processInstance = (ProcessInstanceWithVariables) runtimeService.startProcessInstanceByKey(flowCode, paramMap);
        } catch (Exception e) {
            log.error("流程启动出错", e);
            throw new ServiceException(e.getMessage());
        }

        // 任务结束,组织返回数据
        return getReturnData(processInstance);
    }
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值