流程定义用例实现
平台的流程建模包括了在线流程定义中的比较常见的操作,如:
- 保存草稿
- 发布版本
- 修改
- 流程定义校检
- 设置主版本
- 删除
- 流程的导入导出
- 流程复制
不同的业务操作需要提供不同的应用管理,以支持不同的数据存储的要求与业务实现要求。
类设计

说明:
- BpmDef 流程定义实体类
- BpmModelerController 流程定义建模的保存、检查、修改、发布核心服务对外提供类
- BpmDefController 流程定义控制器,负责流程定义删除、更新、列表查询的对外服务提供类
- BpmDefMapper 为流程定义数据库的操作类
- ActRepService 为Activiti流程库的API封装,如获取流程定义开始节点,结结节点等
流程定义保存、修改、发布
流程定义的保存,只需要在bpmn的设计界面中,实现对流程的基本信息的保存,如流程定义分类,编码,名称,描述,在线的bpmn定义,状态设置为草稿即可。
保存/发布时序图

【说明】
- 根据提交的状态来决定是保存流程定义、修改流程定义、发布流程的区分
- 在保存流程定义之前,处理json,主要是流程定义的节点级的json进行相应的更新
- 处理流程XML中的流程定义名称
- 处理一些子流程与Service节点的特殊节点
- 若是发布流程定义,则需要调用ActRepService实现流程定义的发布,并且生成ActDefId,ActDeployId。并且在BPM_DEF表中记录,为后续的流程启动与任务启动提供数据。
- 流程发布时相应修改流程定义版本,每增加一版本则更新版本号
流程定义修改
流程定义修改是指流程在定义XML发布完成后,即使在流程在运行中,还允许对流程定义进行节点增加、节点属性更改、节点删除等操作,其中节点删除即需要谨慎。若当前节点的任务正在审批,在流程定义中删除该节点时,则会造成该流程实例无法运行。
流程定义修改时,请参考BpmDefService的以下方法:
/*** 发布流程定义。* @param bpmDef* @return* @throws UnsupportedEncodingException*/public BpmDef doModify(BpmDef bpmDef) throws UnsupportedEncodingException {FlowDefCache.removeByDefId(bpmDef.getActDefId());actRepService.writeDefXml(bpmDef.getActDepId(),bpmDef.getDesignXml());update(bpmDef);return bpmDef;}
说明:
- 清空该流程定义的缓存,引擎第一次加载Activiti的流程定义会缓存起来
- 直接实现定义的XML回写
- 更新当前bpmDef的表,主要是设计器的XML
流程定义的发布
为了不影响当前正在运行的流程实例,执行流程定义的发布是比较好的办法,他会基于旧版本的数据重新生成一份新的流程定义,并可基于上面进行修改,如删除任务节点,修改任务节点,增加新的任务节点等。
其实现逻辑请参考BpmDefService类以下方法:
/*** 发布新版流程定义* @param oldBpmDef* @param newBpmDef*/public void doDeployNewVersion(BpmDef oldBpmDef, BpmDef newBpmDef){String oldDefId=oldBpmDef.getDefId();//换成新的newBpmDef.setDefId(IdGenerator.getIdStr());//更新为主版本主键IdnewBpmDef.setMainDefId(newBpmDef.getDefId());newBpmDef.setIsMain(BpmDef.IS_MAIN);newBpmDef.setStatus(BpmDef.STATUS_DEPLOYED);//发布Activiti的流程定义Deployment deployment = activitiDeployService.deploy(newBpmDef.getKey(), newBpmDef.getDesignXml());newBpmDef.setActDepId(deployment.getId());ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).latestVersion().singleResult();//获取流程定义Idif(processDefinition!=null){newBpmDef.setActDefId(processDefinition.getId());}Integer maxVersion=getMaxVersion(newBpmDef.getKey());//升级流程定义版本newBpmDef.setVersion(maxVersion+1);//更新主版本号updateMainDefId(newBpmDef,oldDefId);//插入新流程insert(newBpmDef);//更新流程定义中的扩展属性定义doCopyBpmDefProsAndUpdate(newBpmDef);}
设置主版本
同一流程定义,如报销流程,可允许多个不同的版本,分别为版本1,版本2,版本3,但每次启动流程时,只能启动一个主版本。系统在设计器中刚提供设置主版本。
切换主版本时,只需要把bpmdef表中的对应的记录的main_def_id更新为当前的流程定义行主键,同时把该同一流程定义下的其他版本的记录maindef_id也更新为该主键,同时设置ismain为YES。
参考BpmDefController的以下实现方法即可:
@ApiOperation("设置主版本")@GetMapping("setMainVersion")public JsonResult setMainVersion(@ApiParam @RequestParam String defId){BpmDef bpmDef = bpmDefService.get(defId);bpmDefService.updateMainDefId(bpmDef,bpmDef.getMainDefId());bpmDef.setIsMain(BpmDef.IS_MAIN);bpmDef.setMainDefId(bpmDef.getDefId());bpmDefService.update(bpmDef);return JsonResult.Success("设置主版本成功").setShow(false);}
删除流程定义
流程定义删除时,需要同时删除关联的数据,如流程实例,流程任务,流程审批历史,审批日志等。
public JsonResult del(@ApiParam @RequestParam("ids") String ids) {String[]idArr=ids.split("[,]");for(String id:idArr){BpmDef bpmDef=bpmDefService.get(id);if(bpmDef!=null && StringUtils.isNotEmpty(bpmDef.getActDepId())){bpmDefService.delCacadeFlow(bpmDef);}else{bpmDefService.delete(id);}}JsonResult result=new JsonResult(true,"");result.setMessage("成功执行删除操作!");return result;}
以下为流程定义对应的流程关联的流程实例的数据实现:
/*** 删除流程实例时,级联删除其下的所有相关的记录,包括任务,审批历史,跳转记录等。* <pre>* 1. 删除任务用户。* 2. 删除任务* 3. 删除流程引擎运行数据。* 4. 删除RUNPATH* 5. 删除活动日志。* 6. 删除流程实例* 7. 删除会签数据* 8. 删除审批意见数据* </pre>* @param instId*/@Transactionalpublic void deleteByInstId(Serializable instId) {BpmInst bpmInst=get(instId);if(bpmInst==null){return;}String bpmInstId=bpmInst.getInstId();String actInstId=bpmInst.getActInstId();bpmTaskUserMapper.deleteByInstId((String) instId);bpmTaskMapper.deleteByInstId(bpmInstId);bpmRuPathService.delByInstId(bpmInstId);bpmInstLogService.delByInstId(bpmInstId);bpmInstMapper.deleteById(bpmInstId);bpmCheckHistoryService.delByInstId(bpmInstId);bpmInstDataServiceImpl.removeByInstId(bpmInstId);if(StringUtils.isNotEmpty(actInstId)){bpmSignDataService.deleteByActInstId(actInstId);runtimeService.deleteProcessInstance(actInstId, "remove by user force");}}
流程的导出
流程的导出,允许用户把测试环境下配置好的流程定义一键导出文件,然后再在生产环境下一键导入即可。
参考BpmDefController的以下实现方法即可:
/*** 流程设计导出*/@ApiOperation("流程设计导出")@GetMapping("/doExport")public void doExport(HttpServletResponse response,@ApiParam @RequestParam String defIds)throws Exception{if(StringUtils.isEmpty(defIds)){new Exception("导出失败,请选择要导出的记录。");return;}List<BpmDefExp> defJsons=bpmDefExpImpService.exportBpmDef(defIds);//把每个记录实体转成JSON文件存储Map<String,String> map=new HashMap<>();for (BpmDefExp def:defJsons) {String fileName =def.getBpmDefName()+".json";String defStr = JSONObject.toJSONString(def);map.put(fileName,defStr);}SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String downFileName = "Bpm-Def" + sdf.format(new Date());FileUtil.downloadZip(response,downFileName,map);}
流程导入如下所示,参考BpmDefController的以下实现方法即可:
/*** 流程设计导入* @param request* @return* @throws Exception*/@ApiOperation("导入接口")@RequestMapping("/doImport")public JsonResult doImport(MultipartHttpServletRequest request) throws Exception {MultipartFile file = request.getFile("zipFile");String treeId=request.getParameter("treeId");String formPcTreeId=request.getParameter("formPcTreeId");List<AlterSql> delaySqlList = bpmDefExpImpService.importBpmDefs(file,treeId,formPcTreeId);return JsonResult.Success().setData(delaySqlList).setMessage("导入成功");}
流程复制
流程复制允许用户现有的流程复制出来,然后变更流程编码与名称,复制完成后,允许用户再进行各种属性的变更。现有的流程与新的流程很多配置是一致的,仅有个别属性的差异。
参考BpmDefController的以下实现方法即可:
/*** 复制流程定义* @param bpmDef* @return* @throws Exception*/@ApiOperation("复制流程定义")@PostMapping("/copyDef")public JsonResult copyDef(@RequestBody BpmDef bpmDef) throws Exception{boolean rtn=bpmDefService.isExistKey(bpmDef.getKey());if(rtn){return new JsonResult<>(false, "指定的KEY名称已经被使用!");}try {bpmDefService.copyNew(bpmDef.getDefId(), bpmDef.getKey(), bpmDef.getName(),bpmDef.getDeploy());} catch (Exception e) {e.printStackTrace();return new JsonResult<>(false, "复制失败");}return new JsonResult<>(true, "复制成功");}