需求总是变来变去,产品希望可以实现动态改变工作流程,从而提高系统的灵活性。这就让我有点懵逼了。
查了一些资料,有两种实现方式:
- 前端页面生成bpmn文件,传送给后台,但是对前端的要求比较高。
- 使用Java代码动态更改流程文件,达到修改流程的目的。
这里使用代码的方式来实现,接下来使用一个Demo做一个简单的示例。
一、使用Activiti Modeler画一个流程图
该流程图会保存到数据库的ACT_REP_MODEL表中。
流程图定义如下:
整体定义
开始定义
开始和userTask的箭头定义
userTask定义
userTask和结束的箭头定义
结束定义
二、项目中需要引入的依赖
//Activiti
compile('org.activiti:activiti-spring-boot-starter-basic:5.22.0')
compile('org.activiti:activiti-modeler:5.22.0'){
//排除Security依赖,否则需要输入密码才能访问项目
exclude group: 'org.springframework.security'
}
//布局排版,当使用代码编辑流程图时,需要自动排版,否则会因为找不到位置信息而报错
compile group: 'org.activiti', name: 'activiti-bpmn-layout', version: '5.22.0'
三、使用代码修改流程图
只是个Demo,很多数据是硬编码,熟悉原理后,可以自己写活。注释都写清楚了,不多解释。
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.UserTask;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.*;
/**
* @author kingboy--KingBoyWorld@163.com
* @date 2017/8/31 下午2:39
* @desc 这块是很重要的核心代码,用代码来编辑流程图.
*/
@RestController
@RequestMapping("/modify")
public class ModifyController {
//注入Activiti的RepositoryService
@Resource
RepositoryService repositoryService;
//
@RequestMapping(value = "/modify", method = RequestMethod.GET)
public void modifyBPMN() throws IOException {
//读取指定ID的Model的二进制资源,是Json格式的。
byte[] modelSource = repositoryService.getModelEditorSource("3");
//使用jackson将Model的源信息转换为JsonNode对象
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(modelSource);
//创建一个bpmn的json转换器
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
//将jsonNode对象转换为bpmnModel的对象
BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(jsonNode);
//读取bpmnModel中id为process的流程定义
Process process = bpmnModel.getProcessById("process");
//创建一个UserTask任务,id为b3,
UserTask userTask = new UserTask();
userTask.setId("b3");
userTask.setName("userTask2");
userTask.setAssignee("小金");
//添加到流程中
process.addFlowElement(userTask);
//移除开始和userTask1之间的a2箭头,
process.removeFlowElement("a2");
//创建一个新的箭头从b2指向b3,也就是从userTask1连接到userTask2
SequenceFlow flow1 = new SequenceFlow();
flow1.setSourceRef("b2");
flow1.setTargetRef("b3");
//创建一个新的箭头从b3指向b4,也就是从userTask2连接到结束事件
SequenceFlow flow2 = new SequenceFlow();
flow2.setSourceRef("b3");
flow2.setTargetRef("b4");
//将两个箭头添加到流程定义中
process.addFlowElement(flow1);
process.addFlowElement(flow2);
//对文件进行重新排版,生成位置信息,否则会报错
new BpmnAutoLayout(bpmnModel).execute();
//创建一个bpmn的xml转换器,
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
//这里将结果输出到一个文件中,查看是否成功,(必需成功)
byte[] bytes = xmlConverter.convertToXML(bpmnModel);
FileOutputStream fileOutputStream = new FileOutputStream("/Users/kingboy/Desktop/MyDIY.bpmn");
fileOutputStream.write(bytes);
fileOutputStream.close();
}
}
最终生成的流程图如下:
虽然只是个Demo,但是其中可以演化出很多技能。比如说,我们拿到了bpmn的xml流了,那么肯定就可以直接部署到引擎中了。
这个Demo是修改已有的流程,那么我们可不可以用代码直接新建一个流程图呢?当然是可以的,只要认真看下涉及到的几个类的API,就很容易了。
学的是思想而不能仅仅局限于技术。