当前位置: 首页 > news >正文

java-activiti笔记

版本:activiti7

 <dependency><groupId>org.activiti</groupId><artifactId>activiti-json-converter</artifactId><version>7.0.0.Beta2</version><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId></exclusion></exclusions></dependency><!--activiti与springboot整合包--><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter</artifactId><version>7.0.0.Beta2</version><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId></exclusion></exclusions></dependency>

发布

流程图

会签

这里是将流程图通过bpmn.io插件设计好流程图,存放到服务器端

  public AjaxResult publishBpm(BpmFormVo bpmFormVo) {FileInputStream bpmnfileInputStream = null;try{BpmForm byId = getById(bpmFormVo.getId());xml=BpmFormManager.xmlnsActivitiEmpty(xml);xml=BpmFormManager.gatewaySupply(xml);activitiFlowService.delFlowByDefKey(bpmFormVo.getCode());repositoryService.createDeployment().addString(code+ ProcessConstants.SUFFIX, xml).name(code).key(code).deploy();bpmFormVo.setPublishTime(new Date());bpmFormVo.setState(1);bpmFormMapper.publishBpm(bpmFormVo);if("1".equals(byId.getCountersignature())){bpmCountersignService.bpmPublishHandle(byId,xml);}}catch (Exception e){e.printStackTrace();return AjaxResult.error("部署失败");}finally {try {if(bpmnfileInputStream!=null){bpmnfileInputStream.close();}}catch (Exception e){e.printStackTrace();}}return AjaxResult.success("部署成功");}

重新发布需要做如下处理

    @SneakyThrowspublic void delFlowByDefKey(String code) {List<String> deploymentIdByName = activitiFlowMapper.getDeploymentIdByName(code+ ProcessConstants.SUFFIX);if(CollUtil.isEmpty(deploymentIdByName)){return;}for(String did:deploymentIdByName){repositoryService.deleteDeployment(did);}}

启动

    @Overridepublic ProcessInstance startProcess(String definitionKey, String bussinessId,String userId,String userName, String projectId) {String bpmCode=definitionKey;Authentication.setAuthenticatedUserId(userId);Map<String, Object> map=new HashMap<>();map.put("state",ProcessConstants.AUDIT_YES);map.put("assignee",userId);ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(definitionKey, bussinessId, map);Task task = taskService.createTaskQuery().processDefinitionKey(definitionKey).taskAssignee(userId) //设置任务的负责人.orderByTaskCreateTime().desc().list().get(0);if (task!=null){taskService.addComment(task.getId(), task.getProcessInstanceId(), "流程提交","流程提交成功!");startTaskComplete(bpmCode,projectId,task.getId(),null);}startLogProcessHandle(bpmCode,definitionKey,bussinessId,projectId,userId,userName,processInstance,task);return processInstance;}

将会签中的占位的数据赋值

    @Overridepublic void startTaskComplete(String bpmCode,String projectId,String taskId, Map<String, Object> variables) {BpmForm bpmForm = bpmFormService.queryInfoByCode(bpmCode, projectId);if(variables==null){variables=new HashMap<>();}if(bpmForm!=null&&"1".equals(bpmForm.getCountersignature())){//会签模式Object xmlByKey = activitiFlowMapper.getXmlByKey(bpmForm.getResCode() + ".bpmn");Map<String, List<String>> stringListMap = bpmUtil.collectionUseMap(bpmForm, (byte[]) xmlByKey);variables.putAll(stringListMap);}if(CollUtil.isEmpty(variables)){taskService.complete(taskId);}else{taskService.complete(taskId,variables);}}@SneakyThrowspublic Map<String,List<String>> collectionUseMap(BpmForm bpmForm,byte[] resByte){Map<String,List<String>> result=new HashMap<>();if("0".equals(bpmForm.getCountersignature())){return result;}String resStr = new String(resByte);BpmnModel bpmnModel = ModelUtil.getBpmnModel(resStr);Collection<UserTask> allUserTaskEvent = ModelUtil.getAllUserTaskEvent(bpmnModel);if(CollUtil.isEmpty(allUserTaskEvent)){return result;}SysRoleVo sysRoleVo=new SysRoleVo();sysRoleVo.setProjectId(bpmForm.getProjectId());List<SysRoleVo> sysRoleVos = sysRoleService.queryList(sysRoleVo);SysDept sysDept=new SysDept();sysDept.setProjectId(bpmForm.getProjectId());List<SysDept> sysDepts = sysDeptService.queryList(sysDept);for(UserTask userTask:allUserTaskEvent){if(userTask.hasMultiInstanceLoopCharacteristics()){MultiInstanceLoopCharacteristics loopCharacteristics = userTask.getLoopCharacteristics();String inputDataItem = loopCharacteristics.getInputDataItem();String coll = inputDataItem.replace("${", "").replace("}", "");String[] groups = coll.split("_");if("ROLE".equals(groups[0])){List<String> idListByRoleId = getIdListByRoleId(groups[1], sysRoleVos).getUserIdList();if(CollUtil.isNotEmpty(idListByRoleId)){result.put(coll,idListByRoleId);}}else if("DEPT".equals(groups[0])){List<String> idListByDeptId = getIdListByDeptId(groups[1], sysDepts).getUserIdList();if(CollUtil.isNotEmpty(idListByDeptId)){result.put(coll,idListByDeptId);}}}}return result;}

流程审批

    @SneakyThrowspublic CompletResultVo orSignCompletHandle(String taskId, String result, String remark, String definitionKey, Map<String, Object> variables, String userName){Task task = taskService.createTaskQuery().taskId(taskId).singleResult();taskService.addComment(taskId, task.getProcessInstanceId(), result,remark);if(variables==null){variables=new HashMap<>();}variables.put("state",result);taskService.complete(taskId,variables);CompletResultVo completResultVo=new CompletResultVo();boolean afterHandle = afterHandle(task, userName, remark, result);completResultVo.setAuditEndState(afterHandle);return completResultVo;}boolean afterHandle(Task task,String userName,String remark,String result){//存储审核日志信息QueryWrapper queryWrapper=new QueryWrapper<>();queryWrapper.eq("process_instance_id",task.getProcessInstanceId());BussTask bussTask = bussTaskMapper.selectOne(queryWrapper);//日志记录
completByTaskLogHandle(bussTask,task,task.getProcessInstanceId(),userName,remark, result);//更新结束记录return endHandle(task.getProcessInstanceId(),bussTask,userName);}

判断流程结束后相关操作

    boolean endHandle(String piid,BussTask bussTask,String userName){List<Task> task1 = taskService.createTaskQuery().processInstanceId(piid).list();bussTaskMapper.updateById(bussTask);if(CollUtil.isEmpty(task1)){bussTaskMapper.updateStatus(piid,ProcessConstants.AUDIT_NO);endLogHandle(bussTask);return true;}return false;}

会签审批

    @SneakyThrowspublic CompletResultVo countersignCompletHandle(String taskId, String result, String remark,String definitionKey,String projectId,String userName,Long userId,BpmForm bpmForm){Task task = taskService.createTaskQuery().taskId(taskId).singleResult();String taskDefinitionKey = task.getTaskDefinitionKey();UserTask userTask = getUserTaskByNodeId(bpmForm.getResCode(), taskDefinitionKey);if(userTask==null){return orSignCompletHandle(taskId,result,remark,definitionKey,projectId,null,userName);}if(!userTask.hasMultiInstanceLoopCharacteristics()){return orSignCompletHandle(taskId,result,remark,definitionKey,projectId,null,userName);}MultiInstanceLoopCharacteristics loopCharacteristics = userTask.getLoopCharacteristics();String completionCondition = loopCharacteristics.getCompletionCondition();String codeByInfo = BpmCountersignTypeEnum.getCodeByInfo(completionCondition);Map<String,Object> variables=new HashMap<>();QueryWrapper queryWrapper=new QueryWrapper<>();queryWrapper.eq("process_instance_id",task.getProcessInstanceId());BussTask bussTask = bussTaskMapper.selectOne(queryWrapper);List<LogProcess> bussList = getLogs(bussTask.getBussId(), task.getProcessInstanceId());List<BpmCountersignRecord> bpmCountersignRecords=new ArrayList<>();if(CollUtil.isNotEmpty(bussList)){BpmCountersignRecord bpmCountersignRecord=new BpmCountersignRecord();bpmCountersignRecord.setExecutionId(bussList.get(0).getExecutionId());bpmCountersignRecords= bpmCountersignService.queryListByExeId(bpmCountersignRecord);}BpmCountersign bpmCountersignByTaskInfo = bpmCountersignService.getBpmCountersignByTaskInfo(task.getTaskDefinitionKey(), bussTask.getDefinitionKey());String[] user_split = bpmCountersignByTaskInfo.getUids().split(",");if("all".equals(codeByInfo)){if(ProcessConstants.AUDIT_NO.equals(result)){variables.put("pass",true);variables.put("state",ProcessConstants.AUDIT_NO);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,false,true,bussList);}else{if(user_split.length<=(bpmCountersignRecords.size()+1)){variables.put("pass",true);variables.put("state",ProcessConstants.AUDIT_YES);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,true,true,bussList);}else{variables.put("pass",false);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,false,false,bussList);}}}else if("half".equals(codeByInfo)){if(user_split.length<=(bpmCountersignRecords.size()+1)){int ok_users=0;for(BpmCountersignRecord bpm:bpmCountersignRecords){if(ProcessConstants.AUDIT_YES.equals(bpm.getAuditResult())){ok_users+=1;}}if(ProcessConstants.AUDIT_YES.equals(result)){ok_users+=1;}String state=null;BigDecimal divide = new BigDecimal(ok_users).divide(new BigDecimal(user_split.length), 2, BigDecimal.ROUND_HALF_UP)double doubleValue = divide.doubleValue();if(doubleValue>=0.5){state=ProcessConstants.AUDIT_YES;}else{state=ProcessConstants.AUDIT_NO;}variables.put("state",state);variables.put("pass",true);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,state.equals(ProcessConstants.AUDIT_YES)?true:false,true,bussList);}else{variables.put("pass",false);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,false,false,bussList);}}else if("single".equals(codeByInfo)){if(ProcessConstants.AUDIT_YES.equals(result)) {variables.put("pass",true);variables.put("state",ProcessConstants.AUDIT_YES);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,true,true,bussList);}else{if(user_split.length<=(bpmCountersignRecords.size()+1)){variables.put("pass",true);variables.put("state",ProcessConstants.AUDIT_NO);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,false,true,bussList);}else{variables.put("pass",false);taskService.complete(taskId,variables);countersignRecordHandle(task,bpmForm,userName,userId,bpmCountersignByTaskInfo,result,remark,bussTask,false,false,bussList);}}}CompletResultVo completResultVo=new CompletResultVo();List<LogProcess> bussList2 = getLogs(bussTask.getBussId(), task.getProcessInstanceId());String aname="";if(CollUtil.isNotEmpty(bussList2)){aname=bussList2.get(0).getAssigneeName();}else{aname= bussList.get(0).getAssigneeName();}boolean endHandle = endHandle(task.getProcessInstanceId(), bussTask, aname);completResultVo.setAuditEndState(endHandle);return completResultVo;}//日志及操作记录/**** @param task* @param bpmForm* @param userName* @param userId* @param bpmCountersignByTaskInfo* @param result 当前人的审核状态* @param remark* @param auditState 最终审核状态(会签)* @param isEnd 当前节点是否全部完成*/void countersignRecordHandle(Task task,BpmForm bpmForm,String userName,Long userId,BpmCountersign bpmCountersignByTaskInfo,String result,String remark,BussTask bussTask,boolean auditState,boolean isEnd,List<LogProcess> bussList){LogProcess logRecord=null;if(CollUtil.isEmpty(bussList)){logRecord=new LogProcess();logRecord.setProjectId(bpmForm.getProjectId());String myExeId=UUID.randomUUID().toString();logRecord.setExecutionId(myExeId);logRecord.setBusinessId(bussTask.getBussId());logRecord.setTaskId(task.getId());logRecord.setAssigneeName(bpmCountersignByTaskInfo.getUnames());logRecord.setAssignee(bpmCountersignByTaskInfo.getUids());logRecord.setInstanceId(task.getProcessInstanceId());logRecord.setDefinitionKey(bpmForm.getResCode());if(isEnd){logRecord.setStepType(auditState?ActivitiStepType.approved.getCode():ActivitiStepType.reject.getCode());}else{logRecord.setStepType(ActivitiStepType.unapproved.getCode());}logProcessMapper.insert(logRecord);}else{if(isEnd){logRecord = bussList.get(0);logRecord.setStepType(auditState?ActivitiStepType.approved.getCode():ActivitiStepType.reject.getCode());logProcessMapper.updateById(logRecord);}}BpmCountersignRecord bcr=new BpmCountersignRecord();bcr.setNodeId(task.getTaskDefinitionKey());bcr.setBpmCode(bpmForm.getCode());bcr.setUserId(userId+"");bcr.setUserName(userName);if(logRecord!=null){bcr.setLogId(logRecord.getId());}else{bcr.setLogId(bussList.get(0).getId());}bcr.setBusinessId(bussTask.getBussId());bcr.setAuditRemark(remark);bcr.setAuditResult(result);bcr.setExecutionId(logRecord.getExecutionId());bcr.setProcessInstanceId(task.getProcessInstanceId());bpmCountersignRecordMapper.insert(bcr);}

会签流程表达式枚举,全部通过即通过,半数通过即通过,一人通过即通过:

public enum BpmCountersignTypeEnum {all("all", "${nrOfCompletedInstances==nrOfInstances||pass==true}"),half("half", "${nrOfCompletedInstances/nrOfInstances&gt;=0.5&&pass==true}"),single("single", "${nrOfCompletedInstances>=1&&pass==true}");private final String code;private final String info;BpmCountersignTypeEnum(String code, String info){this.code = code;this.info = info;}public static String getCodeByInfo(String info){if(StringUtils.isBlank(info)){return null;}for(BpmCountersignTypeEnum bct:BpmCountersignTypeEnum.values()){String elEscape = EscapeUtil.elEscape(bct.info);if(info.equals(elEscape)){return bct.code;}}return null;}public String getCode(){return code;}public String getInfo(){return info;}
}

这里:

nrOfInstances:总实例数nrOfCompletedInstances:已完成实例数nrOfActiviteInstances:未完成的实例数

全部通过即通过和一人通过即通过直接处理即可,state是流线走向,按比例通过时,我这里用一张表记录了每次操作,即BpmCountersignRecord,将此次记录作为流程操作记录的子关联表,executionId作为关联键。

其他

每次流程启动表act_ge_bytearray中会出现如下图的数据,这就是会签流程里面的变量数据

当流程审批结束后,var-开头的数据就会消失,hist开头的是act_hi表中相关数据

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • OceanBase V4.2特性解析:简化分区表重命名功能
  • 0101中文乱码-BufferedImage-图片处理
  • 搭载海光3350处理器的高速流量处理模块(用于高速网络数据处理设备应用)
  • Java设计模式-抽象工厂模式-一次性理解透
  • 爬虫配置代理:保护隐私有效地抓取数据
  • C#多线程并发编程深度探索:解锁async、await、Task与lock等关键字的奥秘
  • 【生成式人工智能-八-大型语言模型的能力评估】
  • JAVA集中学习第五周学习记录(二)
  • Spring Boot 快速入门样例【后端 3】
  • Linux Shell实例
  • Python 通过UDP传输超过64k的信息
  • 深度学习入门案例:运用神经网络实现价格分类
  • linux中守护进程管理方式
  • 【学习笔记】Day 14
  • 和等于 k 的最长子数组长度(LeetCode)
  • [译] React v16.8: 含有Hooks的版本
  • css属性的继承、初识值、计算值、当前值、应用值
  • Docker: 容器互访的三种方式
  • Javascript弹出层-初探
  • leetcode98. Validate Binary Search Tree
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Objective-C 中关联引用的概念
  • Python中eval与exec的使用及区别
  • 从伪并行的 Python 多线程说起
  • 读懂package.json -- 依赖管理
  • 关于字符编码你应该知道的事情
  • 听说你叫Java(二)–Servlet请求
  • 系统认识JavaScript正则表达式
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​ssh免密码登录设置及问题总结
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • (2)STM32单片机上位机
  • (31)对象的克隆
  • (Python第六天)文件处理
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)一些感悟
  • .form文件_一篇文章学会文件上传
  • .mp4格式的视频为何不能通过video标签在chrome浏览器中播放?
  • .Net - 类的介绍
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .Net 执行Linux下多行shell命令方法
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .NET的微型Web框架 Nancy
  • .NET中分布式服务
  • .NET中统一的存储过程调用方法(收藏)
  • .vimrc 配置项
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • ::前边啥也没有
  • @GetMapping和@RequestMapping的区别
  • @property python知乎_Python3基础之:property
  • @Value获取值和@ConfigurationProperties获取值用法及比较(springboot)
  • []Telit UC864E 拨号上网