开源工作流案例:https://gitee.com/KonBAI-Q/ruoyi-flowable-plus?_from=gitee_search#https://gitee.com/link?target=http%3A%2F%2F159.75.158.189%2F


 API

工作流引擎案例详解_继承关系

工作流引擎案例详解_流程模型_02编辑工作流引擎案例详解_继承关系_03工作流引擎案例详解_继承关系_04编辑编辑

在Camunda中,API的继承关系主要体现在各个服务接口之间。以下是Camunda中一些常见服务接口的继承关系:

  1. ProcessEngineServices 接口:
  • RepositoryService: 负责管理流程定义和部署。
  • RuntimeService: 负责管理流程实例的执行。
  • TaskService: 负责管理流程任务。
  • IdentityService: 负责管理用户、组和身份验证。
  • HistoryService: 负责查询流程历史数据。
  • ManagementService: 提供引擎管理和维护的访问。
  1. ProcessEngine 接口:
  • 该接口是ProcessEngineServices接口的顶级接口,表示整个流程引擎的入口点,通过它可以获取各种服务接口的实例。
  1. RepositoryService 接口的继承关系:
  • RepositoryService
  • DeploymentQuery: 用于查询部署信息。
  • ProcessDefinitionQuery: 用于查询流程定义信息。
  1. RuntimeService 接口的继承关系:
  • RuntimeService
  • ExecutionQuery: 用于查询执行实例信息。
  • ProcessInstanceQuery: 用于查询流程实例信息。
  • VariableInstanceQuery: 用于查询流程变量实例信息。
  1. TaskService 接口的继承关系:
  • TaskService
  • TaskQuery: 用于查询任务信息。
  1. IdentityService 接口的继承关系:
  • IdentityService
  • UserQuery: 用于查询用户信息。
  • GroupQuery: 用于查询用户组信息。
  1. HistoryService 接口的继承关系:
  • HistoryService
  • HistoricProcessInstanceQuery: 用于查询历史流程实例信息。
  • HistoricTaskInstanceQuery: 用于查询历史任务实例信息。
  1. ManagementService 接口的继承关系:
  • ManagementService
  • JobQuery: 用于查询作业信息。

这些继承关系有助于组织和理解Camunda引擎提供的各种服务接口,使开发人员能够更加方便地使用和管理工作流引擎。

案例

设计BPMN

插入模型

工作流引擎案例详解_继承关系_05

API:repositoryService.newModel() 新建模型

@Override
    public void insertModel(WfModelBo modelBo) {
        Model model = repositoryService.newModel();
        model.setName(modelBo.getModelName());
        model.setKey(modelBo.getModelKey());
        model.setCategory(modelBo.getCategory());
        String metaInfo = buildMetaInfo(new WfMetaInfoDto(), modelBo.getDescription());
        model.setMetaInfo(metaInfo);
        // 保存流程模型
        repositoryService.saveModel(model);
    }

工作流引擎案例详解_流程模型_06

思想学习:

将元数据封装到一个类中,流程创建者当前登录用户,判断内容是否为空然后设置最后转JSON

后续需要修改又反序列化-》修改信息-》序列化JSONUtils

/**
     * 构建模型扩展信息
     * @return
     */
    private String buildMetaInfo(WfMetaInfoDto metaInfo, String description) {
        // 只有非空,才进行设置,避免更新时的覆盖
        if (StringUtils.isNotEmpty(description)) {
            metaInfo.setDescription(description);
        }
        if (StringUtils.isNotEmpty(metaInfo.getCreateUser())) {
            metaInfo.setCreateUser(LoginHelper.getUsername());
        }
        return JsonUtils.toJsonString(metaInfo);
    }

工作流引擎案例详解_表单_07

保存/更新BPMN内容

工作流引擎案例详解_继承关系_08

工作流引擎案例详解_表单_09编辑

API:

repositoryService.getModel

repositoryService.saveModel(newModel)

repositoryService.addModelEditorSource(newModel.getId(), bpmnXmlBytes)

获取模型->XML2BPMN->BPMN获取流程名称和开始节点

思想学习:是否为新版本,更新流程版本

public void saveModel(WfModelBo modelBo) {
        // 查询模型信息
        Model model = repositoryService.getModel(modelBo.getModelId());
        if (ObjectUtil.isNull(model)) {
            throw new RuntimeException("流程模型不存在!");
        }
        BpmnModel bpmnModel = ModelUtils.getBpmnModel(modelBo.getBpmnXml());
        if (ObjectUtil.isEmpty(bpmnModel)) {
            throw new RuntimeException("获取模型设计失败!");
        }
        String processName = bpmnModel.getMainProcess().getName();
        // 获取开始节点
        StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
        if (ObjectUtil.isNull(startEvent)) {
            throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
        }
        // 获取开始节点配置的表单Key
       if (StrUtil.isBlank(startEvent.getFormKey())) {
           throw new RuntimeException("请配置流程表单");
       }
        Model newModel;
        if (Boolean.TRUE.equals(modelBo.getNewVersion())) {
            newModel = repositoryService.newModel();
            newModel.setName(processName);
            newModel.setKey(model.getKey());
            newModel.setCategory(model.getCategory());
            newModel.setMetaInfo(model.getMetaInfo());
            newModel.setVersion(model.getVersion() + 1);
        } else {
            newModel = model;
            // 设置流程名称
            newModel.setName(processName);
        }
        // 保存流程模型
        repositoryService.saveModel(newModel);
        // 保存 BPMN XML
        byte[] bpmnXmlBytes = StringUtils.getBytes(modelBo.getBpmnXml(), StandardCharsets.UTF_8);
        repositoryService.addModelEditorSource(newModel.getId(), bpmnXmlBytes);
    }

工作流引擎案例详解_继承关系_10

部署

API

repositoryService.createDeployment()

repositoryService.createProcessDefinitionQuery()

repositoryService.setProcessDefinitionCategory

核心学习:保存关联表单

工作流引擎案例详解_表单_11

获取流程名称-》获取BPMN-》部署-》创建流程定义并设计流程分类-》保存关联表单

public boolean deployModel(String modelId) {
        // 获取流程模型
        Model model = repositoryService.getModel(modelId);
        if (ObjectUtil.isNull(model)) {
            throw new RuntimeException("流程模型不存在!");
        }
        // 获取流程图
        byte[] bpmnBytes = repositoryService.getModelEditorSource(modelId);
        if (ArrayUtil.isEmpty(bpmnBytes)) {
            throw new RuntimeException("请先设计流程图!");
        }
        String bpmnXml = StringUtils.toEncodedString(bpmnBytes, StandardCharsets.UTF_8);
        BpmnModel bpmnModel = ModelUtils.getBpmnModel(bpmnXml);
        String processName = model.getName() + ProcessConstants.SUFFIX;
        // 部署流程
        Deployment deployment = repositoryService.createDeployment()
            .name(model.getName())
            .key(model.getKey())
            .category(model.getCategory())
            .addBytes(processName, bpmnBytes)
            .deploy();
        ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery()
            .deploymentId(deployment.getId())
            .singleResult();
        // 修改流程定义的分类,便于搜索流程
        repositoryService.setProcessDefinitionCategory(procDef.getId(), model.getCategory());
        // 保存部署表单
        return deployFormService.saveInternalDeployForm(deployment.getId(), bpmnModel);
    }

工作流引擎案例详解_流程模型_12

public boolean saveInternalDeployForm(String deployId, BpmnModel bpmnModel) {
        List<WfDeployForm> deployFormList = new ArrayList<>();
        // 获取开始节点
        StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
        if (ObjectUtil.isNull(startEvent)) {
            throw new RuntimeException("开始节点不存在,请检查流程设计是否有误!");
        }
        // 保存开始节点表单信息
        WfDeployForm startDeployForm = buildDeployForm(deployId, startEvent);
        if (ObjectUtil.isNotNull(startDeployForm)) {
//            System.out.println(startDeployForm.getFormKey());
            deployFormList.add(startDeployForm);
        }
        // 保存用户节点表单信息
        Collection<UserTask> userTasks = ModelUtils.getAllUserTaskEvent(bpmnModel);
        if (CollUtil.isNotEmpty(userTasks)) {
            for (UserTask userTask : userTasks) {
                WfDeployForm userTaskDeployForm = buildDeployForm(deployId, userTask);
                if (ObjectUtil.isNotNull(userTaskDeployForm)) {
//                    System.out.println(userTaskDeployForm.getFormKey());
                    deployFormList.add(userTaskDeployForm);
                }
            }
        }
        // 批量新增部署流程和表单关联信息
        return baseMapper.insertBatch(deployFormList);
    }
    
    /**
     * 构建部署表单关联信息对象
     * @param deployId 部署ID
     * @param node 节点信息
     * @return 部署表单关联对象。若无表单信息(formKey),则返回null
     */
    private WfDeployForm buildDeployForm(String deployId, FlowNode node) {
        String formKey = ModelUtils.getFormKey(node);
        if (StringUtils.isEmpty(formKey)) {
            return null;
        }
        Long formId = Convert.toLong(StringUtils.substringAfter(formKey, "key_"));
        //mybatisPlus还是不太懂,待学习
        WfForm wfForm = formMapper.selectById(formId);
        if (ObjectUtil.isNull(wfForm)) {
            throw new ServiceException("表单信息查询错误");
        }
        WfDeployForm deployForm = new WfDeployForm();
        deployForm.setDeployId(deployId);
        deployForm.setFormKey(formKey);
        deployForm.setNodeKey(node.getId());
        deployForm.setFormName(wfForm.getFormName());
        deployForm.setNodeName(node.getName());
        deployForm.setContent(wfForm.getContent());
        return deployForm;
    }

工作流引擎案例详解_表单_13

发起流程实例