流程定义用例实现

平台的流程建模包括了在线流程定义中的比较常见的操作,如:

  • 保存草稿
  • 发布版本
  • 修改
  • 流程定义校检
  • 设置主版本
  • 删除
  • 流程的导入导出
  • 流程复制

不同的业务操作需要提供不同的应用管理,以支持不同的数据存储的要求与业务实现要求。

类设计

说明:

  1. BpmDef 流程定义实体类
  2. BpmModelerController 流程定义建模的保存、检查、修改、发布核心服务对外提供类
  3. BpmDefController 流程定义控制器,负责流程定义删除、更新、列表查询的对外服务提供类
  4. BpmDefMapper 为流程定义数据库的操作类
  5. ActRepService 为Activiti流程库的API封装,如获取流程定义开始节点,结结节点等

流程定义保存、修改、发布

流程定义的保存,只需要在bpmn的设计界面中,实现对流程的基本信息的保存,如流程定义分类,编码,名称,描述,在线的bpmn定义,状态设置为草稿即可。

保存/发布时序图

【说明】

  1. 根据提交的状态来决定是保存流程定义、修改流程定义、发布流程的区分
  2. 在保存流程定义之前,处理json,主要是流程定义的节点级的json进行相应的更新
  3. 处理流程XML中的流程定义名称
  4. 处理一些子流程与Service节点的特殊节点
  5. 若是发布流程定义,则需要调用ActRepService实现流程定义的发布,并且生成ActDefId,ActDeployId。并且在BPM_DEF表中记录,为后续的流程启动与任务启动提供数据。
  6. 流程发布时相应修改流程定义版本,每增加一版本则更新版本号

流程定义修改

流程定义修改是指流程在定义XML发布完成后,即使在流程在运行中,还允许对流程定义进行节点增加、节点属性更改、节点删除等操作,其中节点删除即需要谨慎。若当前节点的任务正在审批,在流程定义中删除该节点时,则会造成该流程实例无法运行。

流程定义修改时,请参考BpmDefService的以下方法:

  1. /**
  2. * 发布流程定义。
  3. * @param bpmDef
  4. * @return
  5. * @throws UnsupportedEncodingException
  6. */
  7. public BpmDef doModify(BpmDef bpmDef) throws UnsupportedEncodingException {
  8. FlowDefCache.removeByDefId(bpmDef.getActDefId());
  9. actRepService.writeDefXml(bpmDef.getActDepId(),bpmDef.getDesignXml());
  10. update(bpmDef);
  11. return bpmDef;
  12. }

说明:

  1. 清空该流程定义的缓存,引擎第一次加载Activiti的流程定义会缓存起来
  2. 直接实现定义的XML回写
  3. 更新当前bpmDef的表,主要是设计器的XML

流程定义的发布

为了不影响当前正在运行的流程实例,执行流程定义的发布是比较好的办法,他会基于旧版本的数据重新生成一份新的流程定义,并可基于上面进行修改,如删除任务节点,修改任务节点,增加新的任务节点等。

其实现逻辑请参考BpmDefService类以下方法:

  1. /**
  2. * 发布新版流程定义
  3. * @param oldBpmDef
  4. * @param newBpmDef
  5. */
  6. public void doDeployNewVersion(BpmDef oldBpmDef, BpmDef newBpmDef){
  7. String oldDefId=oldBpmDef.getDefId();
  8. //换成新的
  9. newBpmDef.setDefId(IdGenerator.getIdStr());
  10. //更新为主版本主键Id
  11. newBpmDef.setMainDefId(newBpmDef.getDefId());
  12. newBpmDef.setIsMain(BpmDef.IS_MAIN);
  13. newBpmDef.setStatus(BpmDef.STATUS_DEPLOYED);
  14. //发布Activiti的流程定义
  15. Deployment deployment = activitiDeployService.deploy(newBpmDef.getKey(), newBpmDef.getDesignXml());
  16. newBpmDef.setActDepId(deployment.getId());
  17. ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).latestVersion().singleResult();
  18. //获取流程定义Id
  19. if(processDefinition!=null){
  20. newBpmDef.setActDefId(processDefinition.getId());
  21. }
  22. Integer maxVersion=getMaxVersion(newBpmDef.getKey());
  23. //升级流程定义版本
  24. newBpmDef.setVersion(maxVersion+1);
  25. //更新主版本号
  26. updateMainDefId(newBpmDef,oldDefId);
  27. //插入新流程
  28. insert(newBpmDef);
  29. //更新流程定义中的扩展属性定义
  30. doCopyBpmDefProsAndUpdate(newBpmDef);
  31. }

设置主版本

同一流程定义,如报销流程,可允许多个不同的版本,分别为版本1,版本2,版本3,但每次启动流程时,只能启动一个主版本。系统在设计器中刚提供设置主版本。

切换主版本时,只需要把bpmdef表中的对应的记录的main_def_id更新为当前的流程定义行主键,同时把该同一流程定义下的其他版本的记录maindef_id也更新为该主键,同时设置ismain为YES。

参考BpmDefController的以下实现方法即可:

  1. @ApiOperation("设置主版本")
  2. @GetMapping("setMainVersion")
  3. public JsonResult setMainVersion(@ApiParam @RequestParam String defId){
  4. BpmDef bpmDef = bpmDefService.get(defId);
  5. bpmDefService.updateMainDefId(bpmDef,bpmDef.getMainDefId());
  6. bpmDef.setIsMain(BpmDef.IS_MAIN);
  7. bpmDef.setMainDefId(bpmDef.getDefId());
  8. bpmDefService.update(bpmDef);
  9. return JsonResult.Success("设置主版本成功").setShow(false);
  10. }

删除流程定义

流程定义删除时,需要同时删除关联的数据,如流程实例,流程任务,流程审批历史,审批日志等。

  1. public JsonResult del(@ApiParam @RequestParam("ids") String ids) {
  2. String[]idArr=ids.split("[,]");
  3. for(String id:idArr){
  4. BpmDef bpmDef=bpmDefService.get(id);
  5. if(bpmDef!=null && StringUtils.isNotEmpty(bpmDef.getActDepId())){
  6. bpmDefService.delCacadeFlow(bpmDef);
  7. }else{
  8. bpmDefService.delete(id);
  9. }
  10. }
  11. JsonResult result=new JsonResult(true,"");
  12. result.setMessage("成功执行删除操作!");
  13. return result;
  14. }

以下为流程定义对应的流程关联的流程实例的数据实现:

  1. /**
  2. * 删除流程实例时,级联删除其下的所有相关的记录,包括任务,审批历史,跳转记录等。
  3. * <pre>
  4. * 1. 删除任务用户。
  5. * 2. 删除任务
  6. * 3. 删除流程引擎运行数据。
  7. * 4. 删除RUNPATH
  8. * 5. 删除活动日志。
  9. * 6. 删除流程实例
  10. * 7. 删除会签数据
  11. * 8. 删除审批意见数据
  12. * </pre>
  13. * @param instId
  14. */
  15. @Transactional
  16. public void deleteByInstId(Serializable instId) {
  17. BpmInst bpmInst=get(instId);
  18. if(bpmInst==null){
  19. return;
  20. }
  21. String bpmInstId=bpmInst.getInstId();
  22. String actInstId=bpmInst.getActInstId();
  23. bpmTaskUserMapper.deleteByInstId((String) instId);
  24. bpmTaskMapper.deleteByInstId(bpmInstId);
  25. bpmRuPathService.delByInstId(bpmInstId);
  26. bpmInstLogService.delByInstId(bpmInstId);
  27. bpmInstMapper.deleteById(bpmInstId);
  28. bpmCheckHistoryService.delByInstId(bpmInstId);
  29. bpmInstDataServiceImpl.removeByInstId(bpmInstId);
  30. if(StringUtils.isNotEmpty(actInstId)){
  31. bpmSignDataService.deleteByActInstId(actInstId);
  32. runtimeService.deleteProcessInstance(actInstId, "remove by user force");
  33. }
  34. }

流程的导出

流程的导出,允许用户把测试环境下配置好的流程定义一键导出文件,然后再在生产环境下一键导入即可。

参考BpmDefController的以下实现方法即可:

  1. /**
  2. * 流程设计导出
  3. */
  4. @ApiOperation("流程设计导出")
  5. @GetMapping("/doExport")
  6. public void doExport(HttpServletResponse response,@ApiParam @RequestParam String defIds)throws Exception{
  7. if(StringUtils.isEmpty(defIds)){
  8. new Exception("导出失败,请选择要导出的记录。");
  9. return;
  10. }
  11. List<BpmDefExp> defJsons=bpmDefExpImpService.exportBpmDef(defIds);
  12. //把每个记录实体转成JSON文件存储
  13. Map<String,String> map=new HashMap<>();
  14. for (BpmDefExp def:defJsons) {
  15. String fileName =def.getBpmDefName()+".json";
  16. String defStr = JSONObject.toJSONString(def);
  17. map.put(fileName,defStr);
  18. }
  19. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
  20. String downFileName = "Bpm-Def" + sdf.format(new Date());
  21. FileUtil.downloadZip(response,downFileName,map);
  22. }

流程导入如下所示,参考BpmDefController的以下实现方法即可:

  1. /**
  2. * 流程设计导入
  3. * @param request
  4. * @return
  5. * @throws Exception
  6. */
  7. @ApiOperation("导入接口")
  8. @RequestMapping("/doImport")
  9. public JsonResult doImport(MultipartHttpServletRequest request) throws Exception {
  10. MultipartFile file = request.getFile("zipFile");
  11. String treeId=request.getParameter("treeId");
  12. String formPcTreeId=request.getParameter("formPcTreeId");
  13. List<AlterSql> delaySqlList = bpmDefExpImpService.importBpmDefs(file,treeId,formPcTreeId);
  14. return JsonResult.Success().setData(delaySqlList).setMessage("导入成功");
  15. }

流程复制

流程复制允许用户现有的流程复制出来,然后变更流程编码与名称,复制完成后,允许用户再进行各种属性的变更。现有的流程与新的流程很多配置是一致的,仅有个别属性的差异。

参考BpmDefController的以下实现方法即可:

  1. /**
  2. * 复制流程定义
  3. * @param bpmDef
  4. * @return
  5. * @throws Exception
  6. */
  7. @ApiOperation("复制流程定义")
  8. @PostMapping("/copyDef")
  9. public JsonResult copyDef(@RequestBody BpmDef bpmDef) throws Exception{
  10. boolean rtn=bpmDefService.isExistKey(bpmDef.getKey());
  11. if(rtn){
  12. return new JsonResult<>(false, "指定的KEY名称已经被使用!");
  13. }
  14. try {
  15. bpmDefService.copyNew(bpmDef.getDefId(), bpmDef.getKey(), bpmDef.getName(),bpmDef.getDeploy());
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. return new JsonResult<>(false, "复制失败");
  19. }
  20. return new JsonResult<>(true, "复制成功");
  21. }
文档更新时间: 2020-08-15 17:23   作者:csx