activiti7在项目中的结合应用
activiti7作为流程管理的一个工具在项目里为审批这一环节提供了很大的助力。
首先,在后端的pom.xml中引入相关依赖

图中的第一个依赖是流程图生成器,不需要我们做额外的操作,即可根据.xml和.bpmn文件完成流程图,下面就是activiti7的依赖,由于activiti7中自带mybatis会和我们本身项目中的mybatis冲突,所以需要按如图所示的方式排除。
部署与流程定义与前端的数据显示结合
首先是部署与流程定义,一个部署对应一个流程定义,
这是一个完成后的样板图,在流程文件中可以看到我们使用的流程模板(.xml或是.bpmn),接着在后端进行部署与流程定义再使用刚才的流程图生成器就可以拿到写好的流程图。
首先是流程定义部署,左上的那个按钮,点击后出现如图所示的界面
可以选择流程类型,比如请假,或是申报报表之类的,然后文件就是.xml或是.bpmn,描述信息根据需求完成即可,这是前端的提供给用户的部分,放到后端就需要我们在业务层完成合理化验证,部署,流程定义这些部分了
对于合理化验证需要先判空,然后对文件的大小和尾缀进行闲置
if(file == null || file.getSize() == 0 ||bpmnType == null){
throw new RuntimeException("非法参数");
}
if (file.getSize() > 1024 * 1024 * 5){
throw new RuntimeException("文件不能大于5M");
}
String fileName = file.getOriginalFilename();
String extension = FilenameUtils.getExtension(fileName);
if(!("xml".equalsIgnoreCase(extension) || "bpmn".equalsIgnoreCase(extension))){
throw new RuntimeException("文件必须为xml或是bpmn格式");
}
这里使用到了对文件名字处理的工具类,验证完成后开始进行部署和流程定义,这里使用到了repositoryService我们需要@AutoWired引进,然后
Deployment deploy = repositoryService.createDeployment()
.addInputStream(fileName, file.getInputStream())
.deploy();
通过用户传进来的输入流也就是对应的文件来进行部署,方法具体需要的东西直接去api里看就好了,部署之后进行流程定义
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deploy.getId())
.singleResult();
在部署之后,是肯定能拿到部署id的这里面可以有很多种进行流程定义的方式,这里选择id,因为是一个部署一个流程定义所以返回singleResult(单个结果),然后再把页面需要的内容通过指定的实体封装后response给前端就可以了
将.xml或.bpmn返回给前端以及生成对应的流程图
首先,这是一个文件类型的数据,在用户传给后端之后就存在了act_ge_bytearray这张表里,以如图所示的方式存储着

在上面的前端界面可以看到我们需要将这个传来的流程文件显示在前端,这里就使用到了流的方式来完成相关业务,用户传来一个输入流(包含id与type(下面会讲到)),我们完成相关业务后以输出流的方式返回给前端,中间使用IoUtils.copy将两者同步。
InputStream inputStream = busBpmnInfoService.readResource(id ,type);
OutputStream outputStream = response.getOutputStream();
IOUtils.copy(inputStream,outputStream);
在业务层面,合理化验证是一定的,然后这里操作是这样的,如果前端传来的type是.xml说明是流程文件,只需要去数据库中把数据查出来返回去就可以了,如果不是,就需要进行流程图的绘制然后返回给前端
if(id == null || type == null){
throw new RuntimeException("非法参数");
}
BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectById(id);
if (busBpmnInfo == null){
throw new RuntimeException("非法参数");
}
String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();
//查询流程定义
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(processDefinitionKey)
.latestVersion()
.singleResult();
String deploymentId = processDefinition.getDeploymentId();
String resourceName = processDefinition.getResourceName();
if("xml".equalsIgnoreCase(type)){
InputStream i = repositoryService.getResourceAsStream(deploymentId, resourceName);
return i;
}else{
DefaultProcessDiagramGenerator defaultProcessDiagramGenerator = new DefaultProcessDiagramGenerator();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
InputStream inputStream = defaultProcessDiagramGenerator.generateDiagram(bpmnModel, Collections.emptyList(), Collections.emptyList(), "宋体", "宋体", "宋体");
return inputStream;
这里面的方法并不常见,所以需要的参数我们都采用通过api的方式进行查看,这样能保证参数不会错误
撤销
撤销就是根据id进行删除,但是要注意的是,在我们进行部署与流程定义之后,就不单单是我们这个界面对应的表改变了,部署表,流程定义表,甚至是存储通过数据的bytearray表都改变了,所以需要进行级联删除,也就是将cascade设为true,这样才能保证删的彻底,然后因为每次定义同一类型的流程时会出现多个版本,所以需要进行遍历删除,最后在删除业务信息表就可以了
//1.参数合理化校验
if(id == null){
throw new RuntimeException("非法参数");
}
//2.查出流程定义
BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectById(id);
if(busBpmnInfo ==null){
throw new RuntimeException("非法参数");
}
String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();
List
.processDefinitionKey(processDefinitionKey)
.list();
for(ProcessDefinition processDefinition : list){
//3.删除流程定义,级联删除流程实例
repositoryService.deleteDeployment(processDefinition.getDeploymentId(),true);
}
//4.删除业务信息表,
return busBpmnInfoMapper.deleteById(id);