1、Acitviti6.0
如果用到springboot整合activiti的jar包,前端如果是jstl的话,要在activiti-spring-boot-basic的依赖下excultion掉juel-spi的包。
Activiti6.0在5.2版本的基础上将表的细致性更新了,同时表的数量上多了近一倍。而且也没有了5.2版本的activiti-explorer的官方demo,取而代之的是activiti-app,这个demo的使用方法与activiti-explorer的使用方法类似。
将activiti6.0的官方demo下载下来之后解压为activiti-6.0.0,打开目录,进入database,进入create,找到自己所用的数据库类型,然后导入数据库即可。
表的分类:
数据表分类 | 描述 |
---|---|
ACT_GE_* | 通用数据表 |
ACT_RE_* | 流程定义储存表 |
ACT_ID_* | 身份信息表 |
ACT_RU_* | 运行时数据库表 |
ACT_HI_* | 历史数据库表 |
主要用到的表的内容如下(详细表结构与对应实体类):
表名 | 功能作用 |
---|---|
act_ge_property | 属性表(自带) |
act_ge_bytearray | 资源表(储存流程定义相关的资源) |
act_re_deployment | 流程部署记录表 |
act_re_procdef | 流程定义信息表 |
act_re_model | 模型信息表 |
act_procdef_info | 流程定义动态改变信息表 |
act_id_user | 用户的基本信息 |
act_id_info | 用户的拓展信息 |
act_id_group | 群组 |
act_id_membership | 用户与群组的关系 |
act_ru_deadletter_job | 死信表 |
act_ru_event_subscr | 事件监听表 |
act_ru_execution | 流程实例与分支执行信息 |
act_ru_identitylink | 参与者相关信息 |
act_ru_job | 作业表 |
act_ru_suspended_job | 暂停作业表 |
act_ru_task | 用户任务信息 |
act_ru_timer_job | 定时器表 |
act_ru_variable | 变量信息 |
act_hi_actinst | 历史节点信息表 |
act_hi_attachment | 附件 |
act_hi_comment | 评论 |
act_hi_detail | 历史变更 |
act_hi_identitylink | 历史参与者 |
act_hi_procinst | 历史流程实例表 |
act_hi_taskinst | 历史任务表 |
act_hi_varinst | 历史变量 |
act_evt_log | 事件日志 |
2、一个完整的Activiti流程(通过h2数据库进行模拟)
pom文件:
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.11</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
</dependency>
流程图
流程图的内容:
<?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="http://www.activiti.org/test">
<process id="myProcess" name="审批流程" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="submit_form" name="填写审批信息">
<extensionElements>
<activiti:formProperty id="message" name="申请信息" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="name" name="申请人名称" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="subDate" name="提交时间" type="date" datePattern="yyyy-mm-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="subType" name="确认申请" type="string" required="true"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="submit_form"></sequenceFlow>
<exclusiveGateway id="exclusivegateway1" name="提交or取消"></exclusiveGateway>
<sequenceFlow id="flow2" sourceRef="submit_form" targetRef="exclusivegateway1"></sequenceFlow>
<userTask id="pr_form" name="主管审批">
<extensionElements>
<activiti:formProperty id="PrType" name="主管审批结果" type="string"></activiti:formProperty>
<activiti:formProperty id="PrResult" name="主管备注" type="string" required="true"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow3" sourceRef="exclusivegateway1" targetRef="pr_form">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${subType == "y" || subType == "Y"}]]></conditionExpression>
</sequenceFlow>
<exclusiveGateway id="decide_pr" name="主管审批校验"></exclusiveGateway>
<sequenceFlow id="flow4" sourceRef="pr_form" targetRef="decide_pr"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<endEvent id="endevent2" name="取消"></endEvent>
<sequenceFlow id="flow8" sourceRef="exclusivegateway1" targetRef="endevent2">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${subType == "n" || subType == "N"}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow9" sourceRef="decide_pr" targetRef="submit_form">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${PrType == "N" || PrType == "n" }]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow10" sourceRef="decide_pr" targetRef="endevent1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${PrType == "Y" || PrType == "y" }]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
<bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="131.0" y="201.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="submit_form" id="BPMNShape_submit_form">
<omgdc:Bounds height="55.0" width="105.0" x="211.0" y="191.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
<omgdc:Bounds height="40.0" width="40.0" x="360.0" y="198.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="pr_form" id="BPMNShape_pr_form">
<omgdc:Bounds height="55.0" width="105.0" x="445.0" y="191.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="decide_pr" id="BPMNShape_decide_pr">
<omgdc:Bounds height="40.0" width="40.0" x="595.0" y="199.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="720.0" y="202.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent2" id="BPMNShape_endevent2">
<omgdc:Bounds height="35.0" width="35.0" x="445.0" y="320.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="166.0" y="218.0"></omgdi:waypoint>
<omgdi:waypoint x="211.0" y="218.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="316.0" y="218.0"></omgdi:waypoint>
<omgdi:waypoint x="360.0" y="218.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="400.0" y="218.0"></omgdi:waypoint>
<omgdi:waypoint x="445.0" y="218.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="550.0" y="218.0"></omgdi:waypoint>
<omgdi:waypoint x="595.0" y="219.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
<omgdi:waypoint x="380.0" y="238.0"></omgdi:waypoint>
<omgdi:waypoint x="379.0" y="337.0"></omgdi:waypoint>
<omgdi:waypoint x="445.0" y="337.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
<omgdi:waypoint x="615.0" y="199.0"></omgdi:waypoint>
<omgdi:waypoint x="614.0" y="74.0"></omgdi:waypoint>
<omgdi:waypoint x="263.0" y="74.0"></omgdi:waypoint>
<omgdi:waypoint x="263.0" y="191.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
<omgdi:waypoint x="635.0" y="219.0"></omgdi:waypoint>
<omgdi:waypoint x="720.0" y="219.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
注意情况
- 在eclipse中进行绘制图表,idea绘制插件2014年停止更新,很落后
- 网关流转后的输出条上点击,进入main config,在condition中添加 ${PrType == “Y” || PrType == “y” },其中PrType是在前面主管审批节点的form表单中的一个string数据;
- 在填写表单的时候要记住数据类型要小写;
- h2数据库登录哪个用户即为哪个库
- ProcessEngineConfigure有默认配置,默认的h2数据库名称为activiti,账户为sa,密码为空,
登录之后导入activiti所需的数据表; - 部署流程之后获取不到定义,后缀应为*.bpmn20.xml。
- 在eclipse中打开bpmn点击流程图框不显示配置,依次点击window -> perspective -> open perspective -> activiti,即可。
1、创建引擎:
/** 这里代码自动填补返回值 alt + ctrl+v 自动重构代码 alt + shift +M */
/** 获取引擎配置文件,这里查询的是 ACT_GE_PROPERTY */
ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
/** 通过配置文件创建引擎 */
PeocessEngine processEngine = cfg.buildProcessEngine;
String name = processEngine.getName();
String version = processEngine.VERSION;
/** 可以将name version 输出 */
2、部署流程定义文件
/** 部署流程定义文件 */
/** 获取仓库service 往ACT-RE数据库加载数据 */
ReositoryService repositoryService = processEngine.getRepositoryService();
/** 通过仓库服务获取对ACT-DE系列数据表操作的权限 */
DeploymentBuilder deployment = repositoryService.createDeloyment();
/** 加载文件通过获取绝对目录 */
deployment.addClasspathResource("yourPath");
/** 通过该方法将其部署,加载至数据库(两个表一个ACT_GE_BYTEARRAY ,一个SELECT * FROM ACT_RE_DEPLOYMENT )
Deployment deploy = deployment.deploy();
/** 获取部署的id */
String id = deploy.getId();
/** 通过id获取流程实例 */
ProcessDefinition processDefinition = repositoryService.createProcessDefinition.deloymentId(id).singleResult();
/** 可是将流程实例的信息输出查看 */
3、处理流程任务
Scanner sc = new Scanner(System.in);
/** 当流程定义不为空且流程实例没有完成时 */
while (processDefinition != null && !processInstance.isEnd) {
/** 通过引擎获取任务服务 */
TaskService taskService = processEngine.getTaskService();
/** 通过任务服务获取全部待处理任务 */
List<Task> list = taskService.createTaskQuery().list();
/** 可以在这输出一下待处理的任务数 list.size() */
list.forEach(task -> {
/** 待处理任务 task.getName() */
/** 获取表单服务 */
FormService form = processEngine.getFormService();
/** 通过表单服务根据任务id获取任务表单的具体数据类型 */
TaskFormData taskFormData = form.getTaskFormData(task.geId);
/** 获取表单的key-value , key 标题, value */
List<FormPropertty> formProperties = taskFormData.getFormProperties();
/* 用来存放表单标题和输出内容的集合 */
Map<String, Object> map = Maps.newHashMap();
formProperties.forEach(p -> {
String line = null;
/** 判断当前标题所填值得属性进行分类型输入 */
if (StringFormType.class.isInstance(p.getType())) {
line = sc.nextLine();
map.put(p.getId(), line);
} else if (DateFormType.class.isInstance(p.getType())) {
line = sc.nextLine();
SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd");
Date date = sm.parse(line); //这里对其进行捕获处理
map.put(p.getId, line);
} else {
/** 不支持的类型 */
}
/** 可以输出输入的内容 line */
});
/* 通过任务服务来完成当前节点的任务 */
taskService.complete(task.getId(), map);
/** 再获取下一个节点的任务 直至不符合循环 */
processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
});
}