pom.xml引入依赖:
<dependencies>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-jpa</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!-- servlet支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- jstl 支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
在项目根路径下创建process文件夹,创建helloworld.bpmn文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1567831900728" name="" targetNamespace="http://www.activiti.org/testm1567831900728" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="myProcess_1" isClosed="false" isExecutable="true" processType="None">
<startEvent id="_2" name="StartEvent"/>
<endEvent id="_3" name="EndEvent"/>
<userTask activiti:assignee="zhagnsan" activiti:exclusive="true" id="_4" name="apply"/>
<userTask activiti:assignee="lisi" activiti:exclusive="true" id="_5" name="manager apply"/>
<userTask activiti:assignee="wangwu" activiti:exclusive="true" id="_6" name="boss apply"/>
<sequenceFlow id="_7" sourceRef="_2" targetRef="_4"/>
<sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/>
<sequenceFlow id="_9" sourceRef="_5" targetRef="_6"/>
<sequenceFlow id="_10" sourceRef="_6" targetRef="_3"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="myProcess_1">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<dc:Bounds height="32.0" width="32.0" x="75.0" y="170.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<dc:Bounds height="32.0" width="32.0" x="645.0" y="180.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
<dc:Bounds height="55.0" width="85.0" x="190.0" y="165.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
<dc:Bounds height="55.0" width="85.0" x="335.0" y="165.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
<dc:Bounds height="55.0" width="85.0" x="490.0" y="170.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_4">
<di:waypoint x="107.0" y="186.0"/>
<di:waypoint x="190.0" y="192.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5">
<di:waypoint x="275.0" y="192.5"/>
<di:waypoint x="335.0" y="192.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_5" targetElement="_6">
<di:waypoint x="420.0" y="192.5"/>
<di:waypoint x="490.0" y="197.5"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_6" targetElement="_3">
<di:waypoint x="575.0" y="197.5"/>
<di:waypoint x="645.0" y="196.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
application.yml配置数据源
spring:
jpa:
properties:
show-sql: true
hibernate:
hbm2ddl:
auto: update
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
datasource:
url: jdbc:mysql://localhost:3306/activity
username: root
password: 123
driverClassName: com.mysql.jdbc.Driver
minPoolSize: 3
maxPoolSize: 25
activiti:
database-schema-update: true
# 自动部署验证设置:true-开启(默认)、false-关闭
check-process-definitions: false
流程的核心类是ProcessEngine,流程部署,启动,查询都需要
public class HelloWorld {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//默认从项目根目录下的activiti.cfg.xml读取配置信息,springboot可以注入
/**部署流程定义*/
@Test
public void deploymentProcessDefinition(){
Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createDeployment()//创建一个部署对象
.name("helloworld入门程序")//添加部署的名称
.addClasspathResource("process/helloworld.bpmn")//从classpath的资源中加载,一次只能加载一个文件
.addClasspathResource("process/helloworld.png")//从classpath的资源中加载,一次只能加载一个文件
.deploy();//完成部署
System.out.println("部署ID:"+deployment.getId());//1
System.out.println("部署名称:"+deployment.getName());//helloworld入门程序
}
/**启动流程实例*/
@Test
public void startProcessInstance(){
//流程定义的key
String processDefinitionKey = "helloworld";
ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
.startProcessInstanceByKey(processDefinitionKey);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动(同一个key部署多次)
System.out.println("流程实例ID:"+pi.getId());//流程实例ID 101
System.out.println("流程定义ID:"+pi.getProcessDefinitionId());//流程定义ID helloworld:1:4
}
/**查询当前人的个人任务*/
@Test
public void findMyPersonalTask(){
String assignee = "王五";
List<Task> list = processEngine.getTaskService()//与正在执行的任务管理相关的Service
.createTaskQuery()//创建任务查询对象
.taskAssignee(assignee)//指定个人任务查询,指定办理人
.list();
if(list!=null && list.size()>0){
for(Task task:list){
System.out.println("任务ID:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务的创建时间:"+task.getCreateTime());
System.out.println("任务的办理人:"+task.getAssignee());
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("执行对象ID:"+task.getExecutionId());
System.out.println("流程定义ID:"+task.getProcessDefinitionId());
System.out.println("########################################################");
}
}
}
/**完成我的任务*/
@Test
public void completeMyPersonalTask(){
//任务ID
String taskId = "302";
processEngine.getTaskService()//与正在执行的任务管理相关的Service
.complete(taskId);
System.out.println("完成任务:任务ID:"+taskId);
}
}
service的作用:
RepositoryService | 管理流程定义 |
RuntimeService | 执行管理,包括启动、推进、删除流程实例等操作 |
TaskService | 任务管理 |
HistoryService | 历史管理(执行完的数据的管理) |
IdentityService | 组织机构管理 |
FormService | 一个可选服务,任务表单管理,可在节点上设置获取参数 |
ManagerService | Job任务管理;数据库相关通用操作;执行流程引擎命令(Command) |
@Override
public String findTaskFormKeyByTaskId(String taskId) {
TaskFormData formData = formService.getTaskFormData(taskId);
//获取Form key的值
String url = formData.getFormKey();
return url;
}
Deployment 部署对象
1、一次部署的多个文件的信息。对于不需要的流程可以删除和修改。
2、对应的表:
act_re_deployment:部署对象表
act_re_procdef:流程定义表
act_ge_bytearray:资源文件表
act_ge_property:主键生成策略表
ProcessDefinition 流程定义
解析.bpmn后得到的流程定义规则的信息,工作流系统就是按照流程定义的规则执行的。
Execution 执行对象
按流程定义的规则执行一次的过程.
对应的表:
act_ru_execution: 正在执行的信息
act_hi_procinst:已经执行完的历史流程实例信息
act_hi_actinst:存放历史所有完成的活动
ProcessInstance 流程实例
特指流程从开始到结束的那个最大的执行分支,一个执行的流程中,流程实例只有1个。
注意
(1)如果是单例流程,执行对象ID就是流程实例ID
(2)如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同
(3)一个流程中,流程实例只有1个,执行对象可以存在多个。
Task 任务
执行到某任务环节时生成的任务信息。
对应的表:
act_ru_task:正在执行的任务信息
act_hi_taskinst:已经执行完的历史任务信息
public class ProcessDefinitionTest {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**部署流程定义(从classpath)*/
@Test
public void deploymentProcessDefinition_classpath(){
Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createDeployment()//创建一个部署对象
.name("流程定义")//添加部署的名称
.addClasspathResource("process/helloworld.bpmn")//从classpath的资源中加载,一次只能加载一个文件
.addClasspathResource("process/helloworld.png")//从classpath的资源中加载,一次只能加载一个文件
.deploy();//完成部署
System.out.println("部署ID:"+deployment.getId());//
System.out.println("部署名称:"+deployment.getName());//
}
/**部署流程定义(从zip)*/
@Test
public void deploymentProcessDefinition_zip(){
InputStream in = this.getClass().getClassLoader().getResourceAsStream("process/helloworld.zip");
ZipInputStream zipInputStream = new ZipInputStream(in);
Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createDeployment()//创建一个部署对象
.name("流程定义")//添加部署的名称
.addZipInputStream(zipInputStream)//指定zip格式的文件完成部署
.deploy();//完成部署
System.out.println("部署ID:"+deployment.getId());//
System.out.println("部署名称:"+deployment.getName());//
}
/**查询流程定义*/
@Test
public void findProcessDefinition(){
List<ProcessDefinition> list = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createProcessDefinitionQuery()//创建一个流程定义的查询
/**指定查询条件,where条件*/
// .deploymentId(deploymentId)//使用部署对象ID查询
// .processDefinitionId(processDefinitionId)//使用流程定义ID查询
// .processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
// .processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
/**排序*/
.orderByProcessDefinitionVersion().asc()//按照版本的升序排列
// .orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
/**返回的结果集*/
.list();//返回一个集合列表,封装流程定义
// .singleResult();//返回惟一结果集
// .count();//返回结果集数量
// .listPage(firstResult, maxResults);//分页查询
if(list!=null && list.size()>0){
for(ProcessDefinition pd:list){
System.out.println("流程定义ID:"+pd.getId());//流程定义的key+版本+随机生成数
System.out.println("流程定义的名称:"+pd.getName());//对应helloworld.bpmn文件中的name属性值
System.out.println("流程定义的key:"+pd.getKey());//对应helloworld.bpmn文件中的id属性值
System.out.println("流程定义的版本:"+pd.getVersion());//当流程定义的key值相同的相同下,版本升级(同一个key部署多次),默认1
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID:"+pd.getDeploymentId());
System.out.println("#########################################################");
}
}
}
/**删除流程定义*/
@Test
public void deleteProcessDefinition(){
//使用部署ID,完成删除
String deploymentId = "601";
/**
* 不带级联的删除
* 只能删除没有启动的流程,如果流程启动,就会抛出异常
*/
// processEngine.getRepositoryService()//
// .deleteDeployment(deploymentId);
/**
* 级联删除
* 不管流程是否启动,都能可以删除
*/
processEngine.getRepositoryService()//
.deleteDeployment(deploymentId, true);
System.out.println("删除成功!");
}
/**查看流程图
* @throws IOException */
@Test
public void viewPic() throws IOException{
/**将生成图片放到文件夹下*/
String deploymentId = "801";
//获取图片资源名称
List<String> list = processEngine.getRepositoryService()//
.getDeploymentResourceNames(deploymentId);
//定义图片资源的名称
String resourceName = "";
if(list!=null && list.size()>0){
for(String name:list){
if(name.indexOf(".png")>=0){
resourceName = name;
}
}
}
//获取图片的输入流
InputStream in = processEngine.getRepositoryService()//
.getResourceAsStream(deploymentId, resourceName);
//将图片生成到D盘的目录下
File file = new File("D:/"+resourceName);
//将输入流的图片写到D盘下
FileUtils.copyInputStreamToFile(in, file);
}
/***附加功能:查询最新版本的流程定义*/
@Test
public void findLastVersionProcessDefinition(){
List<ProcessDefinition> list = processEngine.getRepositoryService()//
.createProcessDefinitionQuery()//
.orderByProcessDefinitionVersion().asc()//使用流程定义的版本升序排列
.list();
/**
* Map<String,ProcessDefinition>
map集合的key:流程定义的key
map集合的value:流程定义的对象
map集合的特点:当map集合key值相同的情况下,后一次的值将替换前一次的值
*/
Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();
if(list!=null && list.size()>0){
for(ProcessDefinition pd:list){
map.put(pd.getKey(), pd);
}
}
List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values());
if(pdList!=null && pdList.size()>0){
for(ProcessDefinition pd:pdList){
System.out.println("流程定义ID:"+pd.getId());//流程定义的key+版本+随机生成数
System.out.println("流程定义的名称:"+pd.getName());//对应helloworld.bpmn文件中的name属性值
System.out.println("流程定义的key:"+pd.getKey());//对应helloworld.bpmn文件中的id属性值
System.out.println("流程定义的版本:"+pd.getVersion());//当流程定义的key值相同的相同下,版本升级,默认1
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID:"+pd.getDeploymentId());
System.out.println("#########################################################");
}
}
}
/**附加功能:删除流程定义(删除key相同的所有不同版本的流程定义)*/
@Test
public void deleteProcessDefinitionByKey(){
//流程定义的key
String processDefinitionKey = "helloworld";
//先使用流程定义的key查询流程定义,查询出所有的版本
List<ProcessDefinition> list = processEngine.getRepositoryService()//
.createProcessDefinitionQuery()//
.processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
.list();
//遍历,获取每个流程定义的部署ID
if(list!=null && list.size()>0){
for(ProcessDefinition pd:list){
//获取部署ID
String deploymentId = pd.getDeploymentId();
processEngine.getRepositoryService()//
.deleteDeployment(deploymentId, true);
}
}
}
/**查询流程状态(判断流程正在执行,还是结束)*/
@Test
public void isProcessEnd(){
String processInstanceId = "1001";
ProcessInstance pi = processEngine.getRuntimeService()//表示正在执行的流程实例和执行对象
.createProcessInstanceQuery()//创建流程实例查询
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
if(pi==null){
System.out.println("流程已经结束");
}
else{
System.out.println("流程没有结束");
}
}
/**查询历史任务*/
@Test
public void findHistoryTask(){
String taskAssignee = "张三";
List<HistoricTaskInstance> list = processEngine.getHistoryService()//与历史数据(历史表)相关的Service
.createHistoricTaskInstanceQuery()//创建历史任务实例查询
.taskAssignee(taskAssignee)//指定历史任务的办理人
.list();
if(list!=null && list.size()>0){
for(HistoricTaskInstance hti:list){
System.out.println(hti.getId()+" "+hti.getName()+" "+hti.getProcessInstanceId()+" "+hti.getStartTime()+" "+hti.getEndTime()+" "+hti.getDurationInMillis());
System.out.println("################################");
}
}
}
/**查询历史流程实例*/
@Test
public void findHistoryProcessInstance(){
String processInstanceId = "1001";
HistoricProcessInstance hpi = processEngine.getHistoryService()//与历史数据(历史表)相关的Service
.createHistoricProcessInstanceQuery()//创建历史流程实例查询
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
System.out.println(hpi.getId()+" "+hpi.getProcessDefinitionId()+" "+hpi.getStartTime()+" "+hpi.getEndTime()+" "+hpi.getDurationInMillis());
}
}
说明:
- 因为是任务查询,所以从processEngine中应该得到TaskService
- 使用TaskService获取到任务查询对象TaskQuery
- 为查询对象添加查询过滤条件,使用taskAssignee指定任务的办理者(即查询指定用户的代办任务),同时可以添加分页排序等过滤条件
- 调用list方法执行查询,返回办理者为指定用户的任务列表
- 任务ID、名称、办理人、创建时间可以从act_ru_task表中查到。
- 如果assignee属性为部门经理,结果为空。因为现在流程只到了”填写请假申请”阶段,后面的任务还没有执行,即在数据库中没有部门经理可以办理的任务,所以查询不到。
- 一个Task节点和Execution节点是1对1的情况,在task对象中使用Execution_来表示他们之间的关系
- 任务ID在数据库表act_ru_task中对应“ID_”列
关于ProcessDefinitionEntity(流程定义实体)的相关内容
上面的这个图就是对于一个流程的相关内容,这部分要特别注意,是非常重要的一个内容。
public class ProcessDefinitionEntityTest {
/**
* 根据pdid得到processDefinitionEntity
*/
@Test
public void testProcessDefinitionEntity(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 根据pdid得到ProcessDefinitionEntry
*/
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
.getProcessDefinition("qingjia1:1:804");
/**
*ProcessInstance process;
*(ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
* .getDeployedProcessDefinition(process.getProcessDefinitionId())
*/
}
/**
* 根据pdid得到processDefinitionEntity中的activityimpl
*/
@Test
public void testGetActivityImpl(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 根据pdid得到ProcessDefinitionEntry
*/
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
.getProcessDefinition("qingjia1:1:804");
/**
* ActivityImpl是一个对象
* 一个activityImpl代表processDefinitionEntity中的一个节点
*/
List<ActivityImpl> activityImpls = processDefinitionEntity.getActivities();
for (ActivityImpl activityImpl : activityImpls) {
System.out.println(activityImpl.getId());
System.out.print("hegiht:"+activityImpl.getHeight());
System.out.print("width:"+activityImpl.getWidth());
System.out.print(" x:"+activityImpl.getX());
System.out.println(" y:"+activityImpl.getY());
}
}
/**
* 得到ProcessDefinitionEntity中的所有的ActivityImpl的所有的PvmTransition
*/
@Test
public void testSequenceFlow(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 根据pdid得到ProcessDefinitionEntry
*/
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
.getProcessDefinition("qingjia1:1:804");
/**
* ActivityImpl是一个对象
* 一个activityImpl代表processDefinitionEntity中的一个节点
*/
List<ActivityImpl> activityImpls = processDefinitionEntity.getActivities();
for (ActivityImpl activityImpl : activityImpls) {
/**
* 得到一个activityimpl的所有的outgoing
*/
List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
for (PvmTransition pvmTransition : pvmTransitions) {
System.out.println("sequenceFlowId:"+pvmTransition.getId());
}
}
}
/**
* 得到当前正在执行的流程实例的activityimpl-->PvmTransition
*/
@Test
public void testQueryActivityImpl_Ing(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)processEngine.getRepositoryService()
.getProcessDefinition("qingjia:1:504");
//根据piid获取到activityId
ProcessInstance pi = processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processInstanceId("1001")
.singleResult();
//根据流程实例得到当前正在执行的流程实例的正在执行的节点
ActivityImpl activityImpl = processDefinitionEntity.findActivity(pi.getActivityId());
System.out.print("流程实例ID:"+pi.getId());
System.out.print(" 当前正在执行的节点:"+activityImpl.getId());
System.out.print(" hegiht:"+activityImpl.getHeight());
System.out.print(" width:"+activityImpl.getWidth());
System.out.print(" x:"+activityImpl.getX());
System.out.println(" y:"+activityImpl.getY());
}
}
附加:
在activiti任务中,主要分为两大类查询任务(个人任务和组任务):
- 确切指定了办理者的任务,这个任务将成为指定者的私有任务,即个人任务。
- 无法指定具体的某一个人来办理的任务,可以把任务分配给几个人或者一到 多个小组,让这个范围内的用户可以选择性(如有空余时间时)来办理这类任务,即组任务。
Activiti里面本身自带有很多的数据表,它里面都是存在着关联关系,那么如何将其本身的表与我们的实际业务中的表进行关联呢?
解惑:其实,这个对于Activiti早已经想到这个问题,(1)就是通过act_ru_exectution这个表中的business_key这个字段来进行关联,启动流程的时候有个方法第一个参数是流程key,第二个是business_key,第三个是流程变量Map,对于business_key的值我们可以设置为流程key+“:”+业务id;
public LeaveBill findLeaveBillByTaskId(String taskId) {
//1:使用任务ID,查询任务对象Task
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//2:使用任务对象Task获取流程实例ID
String processInstanceId = task.getProcessInstanceId();
//3:使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
//4:使用流程实例对象获取BUSINESS_KEY
String buniness_key = pi.getBusinessKey();
//5:获取BUSINESS_KEY对应的主键ID,使用主键ID,查询请假单对象(LeaveBill.1)
String id = "";
if(StringUtils.isNotBlank(buniness_key)){
//截取字符串,取buniness_key小数点的第2个值
id = buniness_key.split("\\.")[1];
}
//查询请假单对象
//使用hql语句:from LeaveBill o where o.id=1
LeaveBill leaveBill = leaveBillDao.findLeaveBillById(Long.parseLong(id));
return leaveBill;
}
(2)将proc_inst_id即启动流程返回的实例id放到我们的业务表中
act_ge_*:
‘ge’代表general(一般)。普通数据,各种情况都使用的数据。
-
act_ge_bytearray:二进制数据表,用来保存部署文件的大文本数据
1.ID_:资源文件编号,自增长
2.REV_INT:版本号
3.NAME_:资源文件名称
4.DEPLOYMENT_ID_:来自于父表act_re_deployment的主键
5.BYTES_:大文本类型,存储文本字节流 -
act_ge_property:属性数据表,存储这整个流程引擎级别的数据。在初始化表结构时,会默认插入三条记录。
1.NAME_:属性名称
2.VALUE_:属性值
3.REV_INT:版本号
act_hi_*:
’hi’代表 history(历史)。就是这些表包含着历史的相关数据,如结束的流程实例、变量、任务、等等。
-
act_hi_actinst:历史节点表
1.ID_ : 标识
2.PROC_DEF_ID_ :流程定义id
3.PROC_INST_ID_ : 流程实例id
4.EXECUTION_ID_ : 执行实例
5.ACT_ID_ : 节点id
6.ACT_NAME_ : 节点名称
7.ACT_TYPE_ : 节点类型
8.ASSIGNEE_ : 节点任务分配人
9.START_TIME_ : 开始时间
10.END_TIME_ : 结束时间
11.DURATION : 经过时长 -
act_hi_attachment:历史附件表
-
act_hi_comment:历史意见表
1.ID_ :标识
2.TYPE_ : 意见记录类型 为comment 时 为处理意见
3.TIME_ : 记录时间
4.USER_ID_ :
5.TASK_ID_ : 对应任务的id
6.PROC_INST_ID_ : 对应的流程实例的id
7.ACTION_ : 为AddComment 时为处理意见
8.MESSAGE_ : 处理意见
9.FULL_MSG_ : -
act_hi_detail:历史详情表,启动流程或者在任务complete之后,记录历史流程变量
1.ID_ : 标识
2.TYPE_ : variableUpdate 和 formProperty 两种值
3.PROC_INST_ID_ : 对应流程实例id
4.EXECUTION_ID_ : 对应执行实例id
5.TASK_ID_ : 对应任务id
6.ACT_INST_ID : 对应节点id
7.NAME_ : 历史流程变量名称,或者表单属性的名称
8.VAR_TYPE_ : 定义类型
9.REV_ : 版本
10.TIME_ : 导入时间
11.BYTEARRAY_ID_
12.DOUBLE_ : 如果定义的变量或者表单属性的类型为double,他的值存在这里
13.LONG_ : 如果定义的变量或者表单属性的类型为LONG ,他的值存在这里
14.TEXT_ : 如果定义的变量或者表单属性的类型为string,值存在这里
15.TEXT2_: -
act_hi_identitylink:历史流程人员表
-
act_hi_procinst: 历史流程实例表
1.ID_ : 唯一标识
2.PROC_INST_ID_ : 流程ID
3.BUSINESS_KEY_ : 业务编号
4.PROC_DEF_ID_ : 流程定义id
5.START_TIME_ : 流程开始时间
6.ENT__TIME : 结束时间
7.DURATION_ : 流程经过时间
8.START_USER_ID_ : 开启流程用户id
9.START_ACT_ID_ : 开始节点
10.END_ACT_ID_: 结束节点
11.SUPER_PROCESS_INSTANCE_ID_ : 父流程流程id
12.DELETE_REASON_ : 从运行中任务表中删除原因 -
act_hi_taskinst: 历史任务实例表
1.ID_ : 标识
2.PROC_DEF_ID_ : 流程定义id
3.TASK_DEF_KEY_ : 任务定义id
4.PROC_INST_ID_ : 流程实例id
5.EXECUTION_ID_ : 执行实例id
6.PARENT_TASK_ID_ : 父任务id
7.NAME_ : 任务名称
8.DESCRIPTION_ : 说明
9.OWNER_ : 拥有人(发起人)
10.ASSIGNEE_ : 分配到任务的人
11.START__TIME_ : 开始任务时间
12.END_TIME_ : 结束任务时间
13.DURATION_ : 时长
14.DELETE_REASON_ :从运行时任务表中删除的原因
15.PRIORITY_ : 紧急程度
16.DUE_DATE_ : -
act_hi_varinst:历史变量表
act_id_*:
’id’代表 identity(身份)。这些表包含着标识的信息,如用户、用户组、等等。
-
act_id_group:用户组信息表,用来存储用户组信息。
1.ID_:用户组名*
2.REV_INT:版本号
3.NAME_:用户组描述信息*
4.TYPE_:用户组类型 -
act_id_info:用户扩展信息表
-
act_id_membership:用户与用户组对应信息表,用来保存用户的分组信息
1.USER_ID_:用户名
2.GROUP_ID_:用户组名 -
act_id_user:用户信息表
1.ID_:用户名
2.REV_INT:版本号
3.FIRST_:用户名称
4.LAST_:用户姓氏
5.EMAIL_:邮箱
6.PWD_:密码
act_re_*:
’re’代表 repository(仓库)。带此前缀的表包含的是静态信息,如,流程定义、流程的资源(图片、规则,等)。
-
act_re_deployment:部署信息表,用来存储部署时需要持久化保存下来的信息
1.ID_:部署编号,自增长
2.NAME_:部署包的名称
3.DEPLOY_TIME_:部署时间 -
act_re_model 流程设计模型部署表
-
act_re_procdef:业务流程定义数据表
1.ID_:流程ID,由“流程编号:流程版本号:自增长ID”组成
2.CATEGORY_:流程命名空间(该编号就是流程文件targetNamespace的属性值)
3.NAME_:流程名称(该编号就是流程文件process元素的name属性值)
4.KEY_:流程编号(该编号就是流程文件process元素的id属性值)
5.VERSION_:流程版本号(由程序控制,新增即为1,修改后依次加1来完成的)
6.DEPLOYMENT_ID_:部署编号
7.RESOURCE_NAME_:资源文件名称
8.DGRM_RESOURCE_NAME_:图片资源文件名称
9.HAS_START_FROM_KEY_:是否有Start From Key
注:此表和ACT_RE_DEPLOYMENT是多对一的关系,即,一个部署的bar包里可能包含多个流程定义文件,每个流程定义文件都会有一条记录在ACT_REPROCDEF表内,每个流程定义的数据,都会对于ACT_GE_BYTEARRAY表内的一个资源文件和PNG图片文件。和ACT_GE_BYTEARRAY的关联是通过程序用ACT_GE_BYTEARRAY.NAME与ACT_RE_PROCDEF.NAME_完成的,在数据库表结构中没有体现。
act_ru_*:
’ru’代表 runtime(运行时)。就是这个运行时的表存储着流程变量、用户任务、变量、作业,等中的运行时的数据。 activiti 只存储流程实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就使这些运行时的表保持 的小且快。
-
act_ru_event_subscr
-
act_ru_execution:运行时流程执行实例表
1.ID_:主键,这个主键有可能和PROC_INST_ID_相同,相同的情况表示这条记录为主实例记录。
2.REV_:版本,表示数据库表更新次数。
3.PROC_INST_ID_:流程实例编号,一个流程实例不管有多少条分支实例,这个ID都是一致的。
4.BUSINESS_KEY_:业务编号,业务主键,主流程才会使用业务主键,另外这个业务主键字段在表中有唯一约束。
5.PARENT_ID_:找到该执行实例的父级,最终会找到整个流程的执行实例
6.PROC_DEF_ID_:流程定义ID
7.SUPER_EXEC_: 引用的执行模板,这个如果存在表示这个实例记录为一个外部子流程记录,对应主流程的主键ID。
8.ACT_ID_: 节点id,表示流程运行到哪个节点
9.IS_ACTIVE_: 是否活动流程实例
10.IS_CONCURRENT_:是否并发。上图同步节点后为并发,如果是并发多实例也是为1。
11.IS_SCOPE_: 主实例为1,子实例为0。
12.TENANT_ID_ : 这个字段表示租户ID。可以应对多租户的设计。
13.IS_EVENT_SCOPE: 没有使用到事件的情况下,一般都为0。
14.SUSPENSION_STATE_:是否暂停。
-
act_ru_identitylink:运行时流程人员表,主要存储任务节点与参与者的相关信息
1.ID_: 标识
2.REV_: 版本
3.GROUP_ID_: 组织id
4.TYPE_: 类型
5.USER_ID_: 用户id
6.TASK_ID_: 任务id -
act_ru_job
-
act_ru_task:运行时任务节点表
1.ID_:
2.REV_:
3.EXECUTION_ID_: 执行实例的id
4.PROC_INST_ID_: 流程实例的id
5.PROC_DEF_ID_: 流程定义的id,对应act_re_procdef 的id_
6.NAME_: 任务名称,对应 ***task 的name
7.PARENT_TASK_ID_ : 对应父任务
8.DESCRIPTION_:
9.TASK_DEF_KEY_: ***task 的id
10.OWNER_ : 发起人
11.ASSIGNEE_: 分配到任务的人
12.DELEGATION_ : 委托人
13.PRIORITY_: 紧急程度
14.CREATE_TIME_: 发起时间
15.DUE_TIME_:审批时长 -
act_ru_variable:运行时流程变量数据表
1.ID_:标识
2.REV_:版本号
3.TYPE_:数据类型
4.NAME_:变量名
5.EXECUTION_ID_: 执行实例id
6.PROC_INST_ID_: 流程实例id
7.TASK_ID_: 任务id
8.BYTEARRAY_ID_:
9.DOUBLE_:若数据类型为double ,保存数据在此列
10.LONG_: 若数据类型为Long保存数据到此列
11.TEXT_: string 保存到此列
12.TEXT2_: