Activiti 流程部署方式 activi 动态部署(高级源码篇)
Activiti的流程 部署方式有很多种方式,我们可以根据activit工作流引擎提供的ap方式进行部署。
当然了实际需求决定你要使用哪一种api操作,后面的总结详细介绍了使用场景。
下面看一下部署方式。
流程部署的方式在类org.activiti.engine.repository.DeploymentBuilder中定义的部署方接口式如下
:
DeploymentBuilder addInputStream(String resourceName, InputStream inputStream); DeploymentBuilder addClasspathResource(String resource); DeploymentBuilder addString(String resourceName, String text); DeploymentBuilder addZipInputStream(ZipInputStream zipInputStream); DeploymentBuilder addBpmnModel(String resourceName, BpmnModel bpmnModel);
可以看出activit工作流引擎一共提供五种方式进行流程对的部署。
addInputStream 根据流进行部署。
addClasspathResource 根据resource部署。
addString根据字符串部署。
addZipInputStream根据zip流进行部署。
addBpmnModel 根据BpmnModel进行部署。这种方式使用的场景就是我们自己设计一个流程设计器画布,自己去解析成bpmn规范文件。适合动态的拓展。自定义。
下面一一讲解如何使用api去进行部署。
1.1.1. addInputStream方式
流程定义如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="daling">
<process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="usertask1审批" activiti:candidateGroups="1,2"></userTask>
<userTask id="usertask2" name="usertask2审批" activiti:candidateUsers="b,c"></userTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_daling">
<bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="230.0" y="10.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="300.0" y="110.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="280.0" y="192.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="230.0" y="340.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="247.0" y="45.0"></omgdi:waypoint>
<omgdi:waypoint x="352.0" y="110.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="352.0" y="165.0"></omgdi:waypoint>
<omgdi:waypoint x="332.0" y="192.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="332.0" y="247.0"></omgdi:waypoint>
<omgdi:waypoint x="247.0" y="340.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
程序代码如下所示:
InputStream inputStream=ProcessEnginesDemo.class.getClassLoader().getResourceAsStream("demo1.bpmn");
Deployment deploy = repositoryService2.createDeployment().addInputStream("addInputStream", inputStream).deploy();
System.out.println(deploy);
程序的运行结果如下所示:
1.1.2. addClasspathResource方式
流程的定义还是第一种方式的流程图,程序如下所示:
Deployment
deploy2 =repositoryService2.createDeployment().addClasspathResource("demo1.bpmn").deploy();
addClasspathResource中的参数是根据classpath方式加载,如果demo1.bpmn路径在com.daling.ch1.ProcessEnginesDemo包下面则参数参入com/daling/ch1/ProcessEnginesDemo/demo1.bpmn
程序的运行如下图所示:
1.1.3. addString方式
流程的定义还是第一种方式的流程图,程序如下所示:
String str=read("D:\\WorkSpace\\activitidemo\\src\\main\\resources/demo1.bpmn");
Deployment deploy2 = repositoryService2.createDeployment().addString("string", str).deploy();
public static String read(String filePath) {
// 读取txt内容为字符串
StringBuffer txtContent = new StringBuffer();
// 每次读取的byte数
byte[] b = new byte[8 * 1024];
InputStream in = null;
try {
// 文件输入流
in = new FileInputStream(filePath);
while (in.read(b) != -1) {
// 字符串拼接
txtContent.append(new String(b));
}
// 关闭流
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return txtContent.toString();
}
程序的运行效果如下图所示:
1.1.4. addZipInputStream方式
流程的定义还是第一种方式的流程图,只不过讲demo1.bpmn打包成zip文件,结构如下:
程序操作如下所示:
InputStream
inputStream=ProcessEnginesDemo.class.getClassLoader().getResourceAsStream("demo1.zip");
ZipInputStream
zipInputStream=new ZipInputStream(inputStream);
Deployment
deploy2 =repositoryService2.createDeployment().addZipInputStream(zipInputStream).deploy();
程序的输出结果如下图所示:
1.1.5. addBpmnModel方式
这一种方式比较复杂需要自己去手动拼接对象,这里我们就写一个简单的吧。实际开发中如果不够用可以自己扩展根据这个demo具体的实现方式如下:
ProcessEnginesDemo demo = new ProcessEnginesDemo();
RepositoryService repositoryService2 = demo.getRepositoryService();
BpmnModel bpmnModel=new BpmnModel();
StartEvent startEvent=new StartEvent();
startEvent.setId("start1shareniu");
startEvent.setName("start1shareniu");
UserTask userTask=new UserTask();
userTask.setId("userTask1shareniu");
userTask.setName("userTask1shareniu");
EndEvent endEvent=new EndEvent();
endEvent.setId("endEventshareniu");
endEvent.setName("endEventshareniu");
List<SequenceFlow> sequenceFlows=new ArrayList<SequenceFlow>();
List<SequenceFlow> toEnd=new ArrayList<SequenceFlow>();
SequenceFlow s1=new SequenceFlow();
s1.setId("starttouserTask");
s1.setName("starttouserTask");
s1.setSourceRef("start1shareniu");
s1.setTargetRef("userTask1shareniu");
sequenceFlows.add(s1);
SequenceFlow s2=new SequenceFlow();
s2.setId("userTasktoend");
s2.setName("userTasktoend");
s2.setSourceRef("userTask1shareniu");
s2.setTargetRef("endEventshareniu");
toEnd.add(s2);
startEvent.setOutgoingFlows(sequenceFlows);
userTask.setOutgoingFlows(toEnd);
userTask.setIncomingFlows(sequenceFlows);
endEvent.setIncomingFlows(toEnd);
Process process=new Process();
process.setId("process1");
process.addFlowElement(startEvent);
process.addFlowElement(s1);
process.addFlowElement(userTask);
process.addFlowElement(s2);
process.addFlowElement(endEvent);
bpmnModel.addProcess(process);
repositoryService2.createDeployment().addBpmnModel("bpmnModel", bpmnModel).deploy();
程序的输出截下图所示:
总结:
五种方式的总结:
1.如果需要自己开发一套流程设计的话就使用addBpmnModel这种方法吧。这种方式更加灵活,缺点就是需要了解每一个对象的含义,需要对bpmnMode对象中的各个子对象都有所了解。
2.如果项目中的流程图是固定的但是一些候选组或者人或者名称不是固定的,需要从数据库中查询出来赋值在部署使用addString这种方法,配合velocity等叶面静态化工具一起使用。
3.如果需要用户自己上传文件部署的话,可以使用addInputStream和addZipInputStream这两种方式。
Activiti 流程部署方式 activi 动态部署(高级源码篇)的更多相关文章
- Activiti 流程部署方式 activi 动态部署(高级源代码篇)
Activiti的流程 部署方式有非常多种方式,我们能够依据activit工作流引擎提供的ap方式进行部署. 当然了实际需求决定你要使用哪一种api操作,后面的总结具体介绍了使用场景. 以下看一下部署 ...
- activiti 动态配置 activiti 监听引擎启动和初始化(高级源码篇)
1.1.1. 前言 用户故事:现在有这样一个需求,第一个需求:公司的开发环境,测试环境以及线上环境,我们使用的数据库是不一样的,我们必须能够任意的切换数据库进行测试和发布,对数据库连接字符串我们需要加 ...
- Android动态方式破解apk前奏篇(Eclipse动态调试smail源码)
一.前言 今天我们开始apk破解的另外一种方式:动态代码调试破解,之前其实已经在一篇文章中说到如何破解apk了: Android中使用静态方式破解Apk 主要采用的是静态方式,步骤也很简单,首先使用 ...
- Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程
spring-aop-4.3.7.RELEASE 在<Spring AOP高级——源码实现(1)动态代理技术>中介绍了两种动态代理技术,当然在Spring AOP中代理对象的生成也是运用 ...
- MyBatis 源码篇-SQL 执行的流程
本章通过一个简单的例子,来了解 MyBatis 执行一条 SQL 语句的大致过程是怎样的. 案例代码如下所示: public class MybatisTest { @Test public void ...
- [转]RMI方式Ehcache集群的源码分析
RMI方式Ehcache集群的源码分析 Ehcache不仅支持基本的内存缓存,还支持多种方式将本地内存中的缓存同步到其他使用Ehcache的服务器中,形成集群.如下图所示: Ehcache支持 ...
- android浪漫樱花凋零动态壁纸应用源码
android浪漫樱花凋零动态壁纸应用源码,是从那个安卓教程网拿过来的,本项目是一套基于安卓的樱花动态壁纸项目源码,安装以后桌面没有图标,但是可以在修改壁纸-动态壁纸中找到.我的分辨率是480×854 ...
- JAVA设计模式-动态代理(Proxy)源码分析
在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...
- 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解
数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...
随机推荐
- 报错django.db.migrations.exceptions.InconsistentMigrationHistory
Pycharm强大的功能总是让我很是着迷,比如它的makemigrations 和 migrate. 然而某一次,当我再次敲下这熟悉的命令时,它报错了.... Traceback (most rece ...
- [AH/HNOI2017]大佬
题目描述 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语. 你作为一个 OIER,面对这样的事情非常不开心,于 ...
- 【BZOJ3573】【HNOI2014】米特运输
Description 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. D星上有N个城市,我们将其顺序编号为1到N,1号城市 ...
- 2015 多校联赛 ——HDU5386(暴力)
Sample Input 1 3 5 2 2 1 2 3 3 2 1 3 3 3 3 3 3 3 3 3 3 H 2 3 L 2 2 H 3 3 H 1 3 L 2 3 Sample Output ...
- hdu 5120(2014北京—求圆相交)
题意:求环的相交面积 思路: 通过画图可知,面积= 大圆相交面积 - 大小圆相交面积*2 + 小小圆相交面积 再通过圆相交模板计算即可 #include <iostream> #incl ...
- Python中模块之random的功能介绍
random的功能介绍 random模块的方法如下: betavariate 获取一个range(0,1)之前的随机浮点数 方法:random.betavariate(alpha,beta) 返回值: ...
- Debugging TensorFlow models 调试 TensorFlow 模型
Debugging TensorFlow models Symbolic nature of TensorFlow makes it relatively more difficult to debu ...
- C#中Fun简单介绍及运用到项目中与缓存(本地缓存,Redis)结合使用
1.简单介绍Fun C#中Fun和Action有点类似,都是一个委托方法,不同的是Func是有返回值的,而Action没有. (T)此委托封装的方法的参数类型. 备注:详情了解Fun到(https: ...
- Mysql优化--慢查询日志
Mysql 系列文章主页 =============== 默认没有开启慢查询日志功能.如果不是调优需要的话,一般不建议开启. 查看是否开启慢查询日志: SHOW VARIABLES LIKE '%sl ...
- 【vuejs深入二】vue源码解析之一,基础源码结构和htmlParse解析器
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. vuejs是一个优秀的前端mvvm框架,它的易用性和渐进式的理念可以使每一个前端开发人员感到舒服,感到easy.它内 ...