react 前端框架如何驱动企业数字化转型与创新发展
974
2023-05-01
关于在IDEA中SpringBoot项目中activiti工作流的使用详解
记录一下工作流的在Springboot中的使用,,顺便写个demo,概念,什么东西的我就不解释了,如有问题欢迎各位大佬指导一下。
1.创建springboot项目后导入依赖
添加配置之后再springboot启动类后面加上一行代码否则启动时会报错
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
添加数据源以及activiti的配置
spring:
activiti:
database-schema-update: drop‐create
//默认为false,activiti在启动的时候会对比数据库中的表中保存的版本,如果不一样会抛出异常
// true activiti会对数据库中的表进行更新操作,如果表不存在,则自动创建
// create_drop 在activiti启动的时候创建表,关闭时删除表,必须手动关闭
// drop-create 在启动的时候先删除表后再创建新的表
check-process-definitions: false
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
username: root
password: root
2.初始化activiti表
这里一共有3种方式去创建
第一种
@Test
public void initTables() {
//创建数据源
// DriverManagerDataSource dataSource=new DriverManagerDataSource();
// dataSource.setDriverClassName("com.mysql.jdbc.Driver");
// dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");
// dataSource.setUsername("root");
// dataSource.setPassword("root");
// 创建流程引擎的配置
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createStandaloneProcessEngineConfiguration();
configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
configuration.setJdbcUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("root");
// configuration.setDataSource(dataSource);
/**
* ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE 如果数据库里面没有activit的表,也不会创建
* ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP 创建表,使用完之后删除
* ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE 如果数据库里面没有表,就创建
*
* dorp-create 代表如果数据库里面有表,那么先删除再创建
*
*/
//配置表的初始化的方式
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
//得到流程引擎
ProcessEngine processEngine=configuration.buildProcessEngine();
System.out.println(processEngine);
}
第二种配置activiti.cfg.xml
xmlns:context="http://springframework.org/schema/context" xmlns:tx="http://springframework.org/schema/tx" xmlns:aop="http://springframework.org/schema/aop" xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd http://springframework.org/schema/context http://springframework.org/schema/context/spring-context.xsd http://springframework.org/schema/tx http://springframework.org/schema/tx/spring-tx.xsd http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop.xsd">
xmlns:context="http://springframework.org/schema/context" xmlns:tx="http://springframework.org/schema/tx"
xmlns:aop="http://springframework.org/schema/aop" xmlns:xsi="http://w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://springframework.org/schema/beans
http://springframework.org/schema/beans/spring-beans.xsd
http://springframework.org/schema/context
http://springframework.org/schema/context/spring-context.xsd
http://springframework.org/schema/tx
http://springframework.org/schema/tx/spring-tx.xsd
http://springframework.org/schema/aop
http://springframework.org/schema/aop/spring-aop.xsd">
然后写一个测试类
@Test
public void intiTables2() {
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
// 得到流程引擎
ProcessEngine processEngine = configuration.buildProcessEngine();
System.out.println(processEngine);
}
第三种方法
@Test
public void intiTables3() {
//必须创建activiti.cfg.xml 并配置好数据库的信息
ProcessEngine processEngine= ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
}
3.打开数据库查看
我们打开数据库查看数据库,会发现activiti已自动帮我们创建了28张表(有的好像也只有24张表,有兴趣的可以研究一下)
这里为大家解释一下各张表的含义:Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。
ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。
#RepositoryService
Select * from act_ge_bytearray; 二进制文件夹表
Select * from act_re_deployment; 流程部署表
Select * from act_re_procdef; 流程定义表
Select * from act_ge_property; 属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录
#RuntimeService TaskService 运行时数据库表
Select * from act_ru_excution; 流程启动一次只要没有执行完就会有一条数据
Select * from act_ru_task; 可能有多条数据
Select * from act_ru_variable; 记录流程运行时的流程变量
Select * from act_ru_identitylink; 存放流程办理人的信息
#HistoryService 历史数据库表
Select * from act_hi_procinst; 历史流程实例
Select * from act_hi_taskinst; 历史任务实例
Select * from act_hi_actinst; 历史节点表
Select * from act_hi_attachment; 历史附件表
Select * from act_hicomment; 历史意见表
Select * from act_hi_identitylink; 历史流程人员表
Select * from act_hi_detail; 历史详情表提供历史变量查询
Select * from act_hi_procinst; 历史流程实例表
Select * from act_hi_taskinst; 历史任务实例表
Select * from act_hi_varinst; 历史变量表
#IdentityService 这四张表尽量使用自己的一套,难以满足需求
Select * from act_id_group; 用户组信息表
Select * from act_id_info; 用户拓展信息表
Select * from act_id_menbership; 用户与用户组对应表
Select * from act_id_user; 用户信息表
4.接下来开始画请假流程图(需要先安装插件),新建一个bpm文件开始编辑
Assignee相当于办理人的意思 我这里是zhang 提出申请,主管yuan 审核。
5.部署流程流程
// 得到流程引擎
private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
@Test
public void deployProcess01() {
// 得到流程部署的service
RepositoryService repositoryService = this.processEngine.getRepositoryService();
Deployment deploy = repositoryService.createDeployment().name("请假流程").addClasspathResource("activitiTest.bpmn").deploy();
System.out.println("部署成功:流程部署ID:" + deploy.getId());
}
6.启动流程(这里的key与第五部第一张途中对应)
/**
* 启动流程
*/
@Test
public void startProcess() {
RuntimeService runtimeService = this.processEngine.getRuntimeService();
// String processDefinitionId="HelloWorld:1:4";
// runtimeService.startProcessInstanceById(processDefinitionId);
String processDefinitionKey="mytest";
runtimeService.startProcessInstanceByKey(processDefinitionKey);
System.out.println("流程启动成功");
}
7.根据用户查询任务(这里使用流程图中的assignee字段)
@Test
public void queryTask() {
TaskService taskService = this.processEngine.getTaskService();
String assignee="chen";
List
if(null!=list&&list.size()>0) {
for (Task task : list) {
System.out.println("任务ID:"+task.getId());
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("执行实例ID:"+task.getExecutionId());
System.out.println("流程定义ID:"+task.getProcessDefinitionId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务办理人:"+task.getAssignee());
System.out.println("################################");
}
}
}
8.办理任务(配合步骤8查询出taskid然后进行办理任务)
@Test
public void completeTask() {
TaskService taskService = this.processEngine.getTaskService();
String taskId="5005";//步骤8中查询出来的taskId
taskService.complete(taskId);
System.out.println("任务完成");
}
重复7、8两个步骤,自此一个完整的请假流程就完成了。
那么肯定会有人问了,如果我想查看一我们流程定义的信息,流程图,删除流程定义等怎么办呢,话不多说直接上代码
package com.example;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.junit.jupiter.api.Test;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
public class TestProcessProdef {
// 得到流程引擎
private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
* 部署流程使用classpath
*/
@Test
public void deployProcess01() {
// 得到流程部署的service
RepositoryService repositoryService = this.processEngine.getRepositoryService();
Deployment deploy = repositoryService.createDeployment().name("请假流程2").addClasspathResource("activiti.bpmn").deploy();
System.out.println("部署成功:流程部署ID:" + deploy.getId());
}
/**
* 查询流程部署信息 act_re_deployment
*/
@Test
public void queryProcessDeploy() {
RepositoryService repositoryService = this.processEngine.getRepositoryService();
// 创建部署信息的查询
String deploymentId = "1";
// Deployment deploy = repositoryService.createDeploymentQuery()
List
// 条件
// .deploymentId(deploymentId) //根据部署ID去查询
// .deploymentName(name)//根据部署名称去查询
// .deploymentTenantId(tenantId)//根据tenantId去查询
// .deploymentNameLike(nameLike)//根据部署名称模糊查询
// .deploymentTenantIdLike(tenantIdLike)//根据tenantId模糊查询
// 排序
// .orderByDeploymenthttp://Id().asc() //根据部署ID升序
// .orderByDeploymenTime().desc() //根据部署时间降序
// .orderByDeploymentName()//根据部署名称升序
// 结果集
.list(); // 查询返回list集合
// .listPage(firstResult, maxResults) 分页查询返回list集合
// .singleResult(); //返回单个对象
// .count();
/*
* System.out.println("部署ID:"+deploy.getId());
* System.out.println("部署名称:"+deploy.getName());
* System.out.println("部署时间:"+deploy.getDeploymentTime());
*/
// System.out.println(count);
for (Deployment deployment : list) {
System.out.println("部署ID:" + deployment.getId());
System.out.println("部署名称:" + deployment.getName());
System.out.println("部署时间:" + deployment.getDeploymentTime());
System.out.println("########################");
}
}
/**
* 查询流程定义
*/
@Test
public void queryProcDef() {
RepositoryService repositoryService = this.processEngine.getRepositoryService();
List
// 条件
// .deploymentId(deploymentId) 根据部署ID查询
// .deploymentIds(deploymentIds) 根据部署ID的集合查询Set
// .processDefinitionId(processDefinitionId)//根据流程定义IDHelloWorld:1:4
// .processDefinitionIds(processDefinitionIds)//根据流程定义的IDS查询
// .processDefinitionKey(processDefinitionKey)//根据流程定义的的key查询
// .processDefinitionKeyLike(processDefinitionKeyLike)//根据流程定义的的key模糊查询
// .processDefinitionName(processDefinitionName)//根据流程定义的名称查询
// .processDefinitionNameLike(processDefinitionNameLike)//根据流程定义的名称模糊查询
// .processDefinitionResourceName(resourceName)//根据流程图的BPMN文件名查询
// .processDefinitionResourceNameLike(resourceNameLike)//根据流程图的BPMN文件名模糊查询
// .processDefinitionVersion(processDefinitionVersion)//根据流程定义的版本查询
// .processDefinitionVersionGreaterThan(processDefinitionVersion)//version>num
// .processDefinitionVersionGreaterThanOrEquals(processDefinitionVersion)//version>=num
// .processDefinitionVersionLowerThan(processDefinitionVersion)//version // .processDefinitionVersionLowerThanOrEquals(processDefinitionVersion)//version<=num // 排序 // .orderByDeploymentId() // .orderByProcessDefinitionId() // .orderByProcessDefinitionKey() // .orderByProcessDefinitionName() // .orderByProcessDefinitionVersion() // 结果集 .list(); // .listPage(firstResult, maxResults)\ // .count() // .singleResult() if (null != list && list.size() > 0) { for (ProcessDefinition pd : list) { System.out.println("流程定义ID:" + pd.getId()); System.out.println("流程部署ID:" + pd.getDeploymentId()); System.out.println("流程定义KEY:" + pd.getKey()); System.out.println("流程定义的名称:" + pd.getName()); System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name System.out.println("流程定义的版本号:" + pd.getVersion()); System.out.println("##################"); } } } /** * 启动流程 */ @Test public void startProcess() { RuntimeService runtimeService = this.processEngine.getRuntimeService(); String processDefinitionKey = "mytest"; runtimeService.startProcessInstanceByKey(processDefinitionKey); System.out.println("流程启动成功"); } /** * 删除流程定义 */ @Test public void deleteProcessDef() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); String deploymentId = "2501"; // 根据流程部署id删除流程定义 如果当前id的流程正在执行,那么会报错 // repositoryService.deleteDeployment(deploymentId); // 根据流程部署id删除删除流程定义 如果当前id的流程正在执行,会把正在执行的流程数据删除 act_ru_*和act_hi_*表里面的数据 repositoryService.deleteDeployment(deploymentId, true); // repositoryService.deleteDeploymentCascade(deploymentId);==repositoryService.deleteDeployment(deploymentId, true); System.out.println("删除成功"); } /** * 查询流程图 根据流程定义ID */ @Test public void viewProcessImg() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); String processDefinitionId = "mytest:2:2504"; InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId); File file = new File("d:/mytest.png"); try { BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file)); int len = 0; byte[] b = new byte[1024]; while ((len = inputStream.read(b)) != -1) { outputStream.write(b, 0, len); outputStream.flush(); } outputStream.close(); inputStream.close(); System.out.println("查询成功"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 查询流程图 根据流流程部署ID */ @Test public void viewProcessImg2() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); // 根据流程部署ID查询流程定义对象 String deploymentId = "1"; ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .deploymentId(deploymentId).singleResult(); // 从流程定义对象里面查询出流程定义ID String processDefinitionId = processDefinition.getId(); InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId); File file = new File("d:/" + processDefinition.getDiagramResourceName()); try { BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file)); int len = 0; byte[] b = new byte[1024]; while ((len = inputStream.read(b)) != -1) { outputStream.write(b, 0, len); outputStream.flush(); } outputStream.close(); inputStream.close(); System.out.println("查询成功"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 查询最新的流程定义 */ @Test public void queryNewProcessDef() { Map // 查询所有的流程定义根据版本号升序 RepositoryService repositoryService = this.processEngine.getRepositoryService(); List .orderByProcessDefinitionVersion().asc().list(); if (null != list && list.size() > 0) { for (ProcessDefinition pd : list) { map.put(pd.getKey(), pd); } } // 循环map集合 Collection for (ProcessDefinition pd : values) { System.out.println("流程定义ID:" + pd.getId()); System.out.println("流程部署ID:" + pd.getDeploymentId()); System.out.println("流程定义KEY:" + pd.getKey()); System.out.println("流程定义的名称:" + pd.getName()); System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name System.out.println("流程定义的版本号:" + pd.getVersion()); System.out.println("##################"); } } /** * 已知key 附加功能:删除流程定义(删除key相同的所有不同版本的流程定义) */ public void deleteAllSameVersion() { String processDefinitionKey = "mytest"; RepositoryService repositoryService = this.processEngine.getRepositoryService(); // 根据流程定义的key查询流程集合 List .processDefinitionKey(processDefinitionKey).list(); if (null != list && list.size() > 0) { for (ProcessDefinition pd : list) { GQoiz repositoryService.deleteDeployment(pd.getDeploymentId(), true); } } } } 肯定还有人会问,上面的请假流程是走完了,但是没有写请假理由,请假天数,如果是报销单的话 还需要上传报销单据等,那么这个怎么解决呢?这个时候就需要activiti提供给我们的流程变量了,那么什么是流程变量呢? 流程变量在整个工作流中扮演很重要的作用。例如:请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是只对应一个流程实例。也就是说各个流程实例的流程变量是不相互影响的。流程实例结束完成以后流程变量还保存在数据库中(存放到流程变量的历史表中)。图中红框的信息就是流程变量。 那么我们怎么设置流程变量呢,我们启动流程的时候就可以设置流程变量了,见代码: /** * 启动流程 */ @Test public void startProcess() { RuntimeService runtimeService = this.processEngine.getRuntimeService(); String processDefinitionKey = "mytest"; // ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey); //创建流程变量对象 Map variables.put("请假天数", 30);//int variables.put("请假原因", "结婚"); variables.put("请假时间", new Date()); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables); System.out.println("流程启动成功:" + processInstance.getId() + " " + processInstance.getProcessDefinitionId() + " " + processInstance.getProcessInstanceId()); } 说明: 1)流程变量的作用域就是流程实例,所以只要设置就行了,不用管在哪个阶段设置 2)基本类型设置流程变量,在taskService中使用任务ID,定义流程变量的名称,设置流程变量的值。 3)Javabean类型设置获取流程变量,除了需要这个javabean实现了Serializable接口外,还要求流程变量对象的属性不能发生变化,否则抛出异常。解决方案,固定序列化ID 4)设置流程变量的时候,向act_ru_variable这个表添加数据 RuntimeService对象可以设置流程变量和获取流程变量 TaskService对象可以设置流程变量和获取流程变量 Map集合的key表示流程变量的名称 Map集合的value表示流程变量的值 查询流程变量以及查询历史流程变量: /** * 获取流程变量 */ @Test public void getVariables() { RuntimeService runtimeService = this.processEngine.getRuntimeService(); String executionId="2501"; Integer days=(Integer) runtimeService.getVariable(executionId, "请假天数"); Date date=(Date) runtimeService.getVariable(executionId, "请假时间"); User user=(User) runtimeService.getVariable(executionId, "用户对象"); System.out.println(days); System.out.println(date.toLocaleString()); System.out.println(user.getId()+" "+user.getName()); } /** * 7:查询历史的流程变量 */ @Test public void getHistoryVariables() { HistoryService historyService = this.processEngine.getHistoryService(); /*HistoricVariableInstance singleResult = historyService.createHistoricVariableInstanceQuery().id("2503").singleResult();; System.out.println(singleResult.getId()); System.out.println(singleResult.getValue()); System.out.println(singleResult.getVariableName()); System.out.println(singleResult.getVariableTypeName());*/ String processInstanceId="2501"; List for (HistoricVariableInstance hvs : list) { System.out.println("ID"+hvs.getId()); System.out.println("变量值"+hvs.getValue()); System.out.println("变量名"+hvs.getVariableName()); System.out.println("变量类型"+hvs.getVariableTypeName()); System.out.println("#####################"); } } 查询历史流程实例 、查询历史活动 以及查询历史任务 public class TestHistoryQuery { private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine(); HistoryService historyService = this.processEngine.getHistoryService(); /* 1,查询历史流程实例 */ @Test public void historyProcessInstince() { List //条件 // .processDefinitionId(processDefinitionId) // .processDefinitionKey(processDefinitionKey) // .processDefinitionKeyIn(processDefinitionKeys) // .processDefinitionName(processDefinitionName) // .processDefinitionVersion(processDefinitionVersion) // .processInstanceBusinessKey(processInstanceBusinessKey) // .processInstanceId(processInstanceId) // .processInstanceIds(processInstanceIds) //排序 // .orderByProcessDefinitionId() // .orderByProcessInstanceBusinessKey() // .orderByProcessInstanceDuration() // .orderByProcessInstanceStartTime() // .orderByProcessInstanceId() //结果集 .list(); // .listPage(firstResult, maxResults) // .count() // .singleResult(); if(null!=list&&list.size()>0) { for (HistoricProcessInstance hpi : list) { System.out.println("历史流程实例ID:" + hpi.getId()); System.out.println("流程定义ID:" + hpi.getProcessDefinitionId()); System.out.println("历史流程实例的业务ID:" + hpi.getBusinessKey()); System.out.println("流程部署ID:" + hpi.getDeploymentId()); System.out.println("流程定义KEY:" + hpi.getProcessDefinitionKey()); System.out.println("开始活动ID:" + hpi.getStartActivityId()); System.out.println("结束活动ID:" + hpi.getEndActivityId()); System.out.println("########################"); } } } /* 2,查询历史活动 */ @Test public void queryHistoryAct() { List //条件 // .activityId(activityId) // .activityInstanceId(activityInstanceId) // .activityName(activityName) //排序 // .orderByActivityId() // .orderByActivityName() //结果集 .list(); if(null!=list&&list.size()>0) { for (HistoricActivityInstance hai : list) { System.out.println("ID:"+hai.getId()); System.out.println("流程定义ID:"+hai.getProcessDefinitionId()); System.out.println("流程实例ID:"+hai.getProcessInstanceId()); System.out.println("执行实例ID:"+hai.getExecutionId()); System.out.println("活动ID:"+hai.getActivityId()); System.out.println("任务ID:"+hai.getTaskId()); System.out.println("活动名称:"+hai.getActivityName()); System.out.println("活动类型:"+hai.getActivityType()); System.out.println("任务办理人:"+hai.getAssignee()); System.out.println("开始时间:"+hai.getStartTime()); System.out.println("结束时间:"+hai.getEndTime()); System.out.println("持续时间:"+hai.getDurationInMillis()); System.out.println("#######################################"); } } } /* 3,查询历史任务 act_hi_taskinst */ @Test public void queryHistoryTask() { List //条件 // .deploymentId(deploymentId) // .deploymentIdIn(deploymentIds) // .executionId(executionId) // .processDefinitionId(processDefinitionId) // .processDefinitionKey(processDefinitionKey) // .processDefinitionKeyIn(processDefinitionKeys) // .processDefinitionKeyLike(processDefinitionKeyLike) processDefinitionKeyLike="%Hello%" // .processDefinitionName(processDefinitionName) // .processDefinitionNameLike(processDefinitionNameLike) //排序 // .orderByTaskDefinitionKey() //结果集 .list(); // .listPage(firstResult, maxResults) // .count() // .singleResult() if(null!=list&&list.size()>0) { for (HistoricTaskInstance task : list) { System.out.println("任务ID:" + task.getId()); System.out.println("任务办理人:" + task.getAssignee()); System.out.println("执行实例ID:" + task.getExecutionId()); System.out.println("任务名称:" + task.getName()); System.out.println("流程定义ID:" + task.getProcessDefinitionId()); System.out.println("流程实例ID:" + task.getProcessInstanceId()); System.out.println("任务创建时间:" + task.getCreateTime()); System.out.println("任务结束时间:" + task.getEndTime()); System.out.println("#######################################"); } } } } 最近我发现上面的代码不能完全在开发中应用,比如上面的用户申请是在画流程图的时候写死的,在实际开发中肯定是根据当前登录的用户来提出申请,另外还没有分支的情况,所以我特地修改了一下流程图。 这个流程图中 没有设置用户,在Condition中传入参数#{UserId},后面的重要与不重要分支同样加上Condition条件${message=='重要'}和${message=='不重要'},然后主管审核和总经理的assignee可以设置成固定的值也可以像用户一样根据传参设置。接下来直接上代码 1.启动流程 /**启动流程实例*/ @Test public void startProcessInstance(){ String processDefinitionKey = "myProcess_1"; /**启动流程实例的同时,设置流程变量,使用流程变量用来指定任务的办理人,对应task.pbmn文件中#{userID}*/ Map variables.put("userID", "袁志豪"); ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service .startProcessInstanceByKey(processDefinitionKey,variables);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动 System.out.println("流程实例ID:"+pi.getId());//流程实例ID 101 System.out.println("流程定义ID:"+pi.getProcessDefinitionId());//流程定义ID } 用户完成申请提交,主管在流成图中没有设置固定值 @Test public void completeTask() { TaskService taskService = this.processEngine.getTaskService(); String taskId = "2508"; // 根据任务ID去完成任务 // taskService.complete(taskId); // 根据任务ID去完成任务并指定流程变量 Map String shenheren ="张三";//实际开发中可在前台选择主管传入后台 variable.put("zhuguan","张三");//这里的 zhuguan 和 activiti.bpmn中的#{zhuguan}保持一致,既可以设置下一级审核主管 taskService.complete(taskId, variables); System.out.println("任务完成"); } 主管审核 @Test public void complateTask2(){ TaskService taskService = this.processEngine.getTaskService(); String taskId2= "5002"; Map /***这里的message 是流程图中分支条件message,根据传入的参数判断走那一条线***/ variable.put("message","重要"); // variable.put("message","不重要"); taskService.complete(taskId2,variable); } 经理审核 @Test public void complateTask3(){ TaskService taskService = this.processEngine.getTaskService(); String taskId2= "7503"; Map variable.put("审核意见","好好休假注意身体");//领导审核意见 taskService.complete(taskId2,variable); } 另外我在开发中发现在流程图画完之后将bpmn后缀改为xml方式生成图片之后,再次改为bpmn的时候,发现之前写的Condition中变成了\n,如图 我们再次将后缀改为xml之后查看我们的条件: 解决方式: 将condition前面后面的空格删掉即可;
// .processDefinitionVersionLowerThanOrEquals(processDefinitionVersion)//version<=num
// 排序
// .orderByDeploymentId()
// .orderByProcessDefinitionId()
// .orderByProcessDefinitionKey()
// .orderByProcessDefinitionName()
// .orderByProcessDefinitionVersion()
// 结果集
.list();
// .listPage(firstResult, maxResults)\
// .count()
// .singleResult()
if (null != list && list.size() > 0) {
for (ProcessDefinition pd : list) {
System.out.println("流程定义ID:" + pd.getId());
System.out.println("流程部署ID:" + pd.getDeploymentId());
System.out.println("流程定义KEY:" + pd.getKey());
System.out.println("流程定义的名称:" + pd.getName());
System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name
System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name
System.out.println("流程定义的版本号:" + pd.getVersion());
System.out.println("##################");
}
}
}
/**
* 启动流程
*/
@Test
public void startProcess() {
RuntimeService runtimeService = this.processEngine.getRuntimeService();
String processDefinitionKey = "mytest";
runtimeService.startProcessInstanceByKey(processDefinitionKey);
System.out.println("流程启动成功");
}
/**
* 删除流程定义
*/
@Test
public void deleteProcessDef() {
RepositoryService repositoryService = this.processEngine.getRepositoryService();
String deploymentId = "2501";
// 根据流程部署id删除流程定义 如果当前id的流程正在执行,那么会报错
// repositoryService.deleteDeployment(deploymentId);
// 根据流程部署id删除删除流程定义 如果当前id的流程正在执行,会把正在执行的流程数据删除 act_ru_*和act_hi_*表里面的数据
repositoryService.deleteDeployment(deploymentId, true);
// repositoryService.deleteDeploymentCascade(deploymentId);==repositoryService.deleteDeployment(deploymentId, true);
System.out.println("删除成功");
}
/**
* 查询流程图 根据流程定义ID
*/
@Test
public void viewProcessImg() {
RepositoryService repositoryService = this.processEngine.getRepositoryService();
String processDefinitionId = "mytest:2:2504";
InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);
File file = new File("d:/mytest.png");
try {
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
int len = 0;
byte[] b = new byte[1024];
while ((len = inputStream.read(b)) != -1) {
outputStream.write(b, 0, len);
outputStream.flush();
}
outputStream.close();
inputStream.close();
System.out.println("查询成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 查询流程图 根据流流程部署ID
*/
@Test
public void viewProcessImg2() {
RepositoryService repositoryService = this.processEngine.getRepositoryService();
// 根据流程部署ID查询流程定义对象
String deploymentId = "1";
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deploymentId).singleResult();
// 从流程定义对象里面查询出流程定义ID
String processDefinitionId = processDefinition.getId();
InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId);
File file = new File("d:/" + processDefinition.getDiagramResourceName());
try {
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
int len = 0;
byte[] b = new byte[1024];
while ((len = inputStream.read(b)) != -1) {
outputStream.write(b, 0, len);
outputStream.flush();
}
outputStream.close();
inputStream.close();
System.out.println("查询成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 查询最新的流程定义
*/
@Test
public void queryNewProcessDef() {
Map
// 查询所有的流程定义根据版本号升序
RepositoryService repositoryService = this.processEngine.getRepositoryService();
List
.orderByProcessDefinitionVersion().asc().list();
if (null != list && list.size() > 0) {
for (ProcessDefinition pd : list) {
map.put(pd.getKey(), pd);
}
}
// 循环map集合
Collection
for (ProcessDefinition pd : values) {
System.out.println("流程定义ID:" + pd.getId());
System.out.println("流程部署ID:" + pd.getDeploymentId());
System.out.println("流程定义KEY:" + pd.getKey());
System.out.println("流程定义的名称:" + pd.getName());
System.out.println("流程定义的bpmn文件名:" + pd.getResourceName());// bpmn的name
System.out.println("流程图片名:" + pd.getDiagramResourceName());// png的name
System.out.println("流程定义的版本号:" + pd.getVersion());
System.out.println("##################");
}
}
/**
* 已知key 附加功能:删除流程定义(删除key相同的所有不同版本的流程定义)
*/
public void deleteAllSameVersion() {
String processDefinitionKey = "mytest";
RepositoryService repositoryService = this.processEngine.getRepositoryService();
// 根据流程定义的key查询流程集合
List
.processDefinitionKey(processDefinitionKey).list();
if (null != list && list.size() > 0) {
for (ProcessDefinition pd : list) {
GQoiz repositoryService.deleteDeployment(pd.getDeploymentId(), true);
}
}
}
}
肯定还有人会问,上面的请假流程是走完了,但是没有写请假理由,请假天数,如果是报销单的话 还需要上传报销单据等,那么这个怎么解决呢?这个时候就需要activiti提供给我们的流程变量了,那么什么是流程变量呢?
流程变量在整个工作流中扮演很重要的作用。例如:请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是只对应一个流程实例。也就是说各个流程实例的流程变量是不相互影响的。流程实例结束完成以后流程变量还保存在数据库中(存放到流程变量的历史表中)。图中红框的信息就是流程变量。
那么我们怎么设置流程变量呢,我们启动流程的时候就可以设置流程变量了,见代码:
/**
* 启动流程
*/
@Test
public void startProcess() {
RuntimeService runtimeService = this.processEngine.getRuntimeService();
String processDefinitionKey = "mytest";
// ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
//创建流程变量对象
Map
variables.put("请假天数", 30);//int
variables.put("请假原因", "结婚");
variables.put("请假时间", new Date());
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
System.out.println("流程启动成功:" + processInstance.getId() + " " + processInstance.getProcessDefinitionId() + " "
+ processInstance.getProcessInstanceId());
}
说明:
1)流程变量的作用域就是流程实例,所以只要设置就行了,不用管在哪个阶段设置
2)基本类型设置流程变量,在taskService中使用任务ID,定义流程变量的名称,设置流程变量的值。
3)Javabean类型设置获取流程变量,除了需要这个javabean实现了Serializable接口外,还要求流程变量对象的属性不能发生变化,否则抛出异常。解决方案,固定序列化ID
4)设置流程变量的时候,向act_ru_variable这个表添加数据
RuntimeService对象可以设置流程变量和获取流程变量 TaskService对象可以设置流程变量和获取流程变量
Map集合的key表示流程变量的名称 Map集合的value表示流程变量的值
查询流程变量以及查询历史流程变量:
/**
* 获取流程变量
*/
@Test
public void getVariables() {
RuntimeService runtimeService = this.processEngine.getRuntimeService();
String executionId="2501";
Integer days=(Integer) runtimeService.getVariable(executionId, "请假天数");
Date date=(Date) runtimeService.getVariable(executionId, "请假时间");
User user=(User) runtimeService.getVariable(executionId, "用户对象");
System.out.println(days);
System.out.println(date.toLocaleString());
System.out.println(user.getId()+" "+user.getName());
}
/**
* 7:查询历史的流程变量
*/
@Test
public void getHistoryVariables() {
HistoryService historyService = this.processEngine.getHistoryService();
/*HistoricVariableInstance singleResult = historyService.createHistoricVariableInstanceQuery().id("2503").singleResult();;
System.out.println(singleResult.getId());
System.out.println(singleResult.getValue());
System.out.println(singleResult.getVariableName());
System.out.println(singleResult.getVariableTypeName());*/
String processInstanceId="2501";
List
for (HistoricVariableInstance hvs : list) {
System.out.println("ID"+hvs.getId());
System.out.println("变量值"+hvs.getValue());
System.out.println("变量名"+hvs.getVariableName());
System.out.println("变量类型"+hvs.getVariableTypeName());
System.out.println("#####################");
}
}
查询历史流程实例 、查询历史活动 以及查询历史任务
public class TestHistoryQuery {
private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
HistoryService historyService = this.processEngine.getHistoryService();
/* 1,查询历史流程实例 */
@Test
public void historyProcessInstince() {
List
//条件
// .processDefinitionId(processDefinitionId)
// .processDefinitionKey(processDefinitionKey)
// .processDefinitionKeyIn(processDefinitionKeys)
// .processDefinitionName(processDefinitionName)
// .processDefinitionVersion(processDefinitionVersion)
// .processInstanceBusinessKey(processInstanceBusinessKey)
// .processInstanceId(processInstanceId)
// .processInstanceIds(processInstanceIds)
//排序
// .orderByProcessDefinitionId()
// .orderByProcessInstanceBusinessKey()
// .orderByProcessInstanceDuration()
// .orderByProcessInstanceStartTime()
// .orderByProcessInstanceId()
//结果集
.list();
// .listPage(firstResult, maxResults)
// .count()
// .singleResult();
if(null!=list&&list.size()>0) {
for (HistoricProcessInstance hpi : list) {
System.out.println("历史流程实例ID:" + hpi.getId());
System.out.println("流程定义ID:" + hpi.getProcessDefinitionId());
System.out.println("历史流程实例的业务ID:" + hpi.getBusinessKey());
System.out.println("流程部署ID:" + hpi.getDeploymentId());
System.out.println("流程定义KEY:" + hpi.getProcessDefinitionKey());
System.out.println("开始活动ID:" + hpi.getStartActivityId());
System.out.println("结束活动ID:" + hpi.getEndActivityId());
System.out.println("########################");
}
}
}
/* 2,查询历史活动 */
@Test
public void queryHistoryAct() {
List
//条件
// .activityId(activityId)
// .activityInstanceId(activityInstanceId)
// .activityName(activityName)
//排序
// .orderByActivityId()
// .orderByActivityName()
//结果集
.list();
if(null!=list&&list.size()>0)
{
for (HistoricActivityInstance hai : list) {
System.out.println("ID:"+hai.getId());
System.out.println("流程定义ID:"+hai.getProcessDefinitionId());
System.out.println("流程实例ID:"+hai.getProcessInstanceId());
System.out.println("执行实例ID:"+hai.getExecutionId());
System.out.println("活动ID:"+hai.getActivityId());
System.out.println("任务ID:"+hai.getTaskId());
System.out.println("活动名称:"+hai.getActivityName());
System.out.println("活动类型:"+hai.getActivityType());
System.out.println("任务办理人:"+hai.getAssignee());
System.out.println("开始时间:"+hai.getStartTime());
System.out.println("结束时间:"+hai.getEndTime());
System.out.println("持续时间:"+hai.getDurationInMillis());
System.out.println("#######################################");
}
}
}
/* 3,查询历史任务 act_hi_taskinst */
@Test
public void queryHistoryTask() {
List
//条件
// .deploymentId(deploymentId)
// .deploymentIdIn(deploymentIds)
// .executionId(executionId)
// .processDefinitionId(processDefinitionId)
// .processDefinitionKey(processDefinitionKey)
// .processDefinitionKeyIn(processDefinitionKeys)
// .processDefinitionKeyLike(processDefinitionKeyLike) processDefinitionKeyLike="%Hello%"
// .processDefinitionName(processDefinitionName)
// .processDefinitionNameLike(processDefinitionNameLike)
//排序
// .orderByTaskDefinitionKey()
//结果集
.list();
// .listPage(firstResult, maxResults)
// .count()
// .singleResult()
if(null!=list&&list.size()>0)
{
for (HistoricTaskInstance task : list) {
System.out.println("任务ID:" + task.getId());
System.out.println("任务办理人:" + task.getAssignee());
System.out.println("执行实例ID:" + task.getExecutionId());
System.out.println("任务名称:" + task.getName());
System.out.println("流程定义ID:" + task.getProcessDefinitionId());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务结束时间:" + task.getEndTime());
System.out.println("#######################################");
}
}
}
}
最近我发现上面的代码不能完全在开发中应用,比如上面的用户申请是在画流程图的时候写死的,在实际开发中肯定是根据当前登录的用户来提出申请,另外还没有分支的情况,所以我特地修改了一下流程图。
这个流程图中 没有设置用户,在Condition中传入参数#{UserId},后面的重要与不重要分支同样加上Condition条件${message=='重要'}和${message=='不重要'},然后主管审核和总经理的assignee可以设置成固定的值也可以像用户一样根据传参设置。接下来直接上代码
1.启动流程
/**启动流程实例*/
@Test
public void startProcessInstance(){
String processDefinitionKey = "myProcess_1";
/**启动流程实例的同时,设置流程变量,使用流程变量用来指定任务的办理人,对应task.pbmn文件中#{userID}*/
Map
variables.put("userID", "袁志豪");
ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
.startProcessInstanceByKey(processDefinitionKey,variables);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动
System.out.println("流程实例ID:"+pi.getId());//流程实例ID 101
System.out.println("流程定义ID:"+pi.getProcessDefinitionId());//流程定义ID
}
用户完成申请提交,主管在流成图中没有设置固定值
@Test
public void completeTask() {
TaskService taskService = this.processEngine.getTaskService();
String taskId = "2508";
// 根据任务ID去完成任务
// taskService.complete(taskId);
// 根据任务ID去完成任务并指定流程变量
Map
String shenheren ="张三";//实际开发中可在前台选择主管传入后台
variable.put("zhuguan","张三");//这里的 zhuguan 和 activiti.bpmn中的#{zhuguan}保持一致,既可以设置下一级审核主管
taskService.complete(taskId, variables);
System.out.println("任务完成");
}
主管审核
@Test
public void complateTask2(){
TaskService taskService = this.processEngine.getTaskService();
String taskId2= "5002";
Map
/***这里的message 是流程图中分支条件message,根据传入的参数判断走那一条线***/
variable.put("message","重要");
// variable.put("message","不重要");
taskService.complete(taskId2,variable);
}
经理审核
@Test
public void complateTask3(){
TaskService taskService = this.processEngine.getTaskService();
String taskId2= "7503";
Map
variable.put("审核意见","好好休假注意身体");//领导审核意见
taskService.complete(taskId2,variable);
}
另外我在开发中发现在流程图画完之后将bpmn后缀改为xml方式生成图片之后,再次改为bpmn的时候,发现之前写的Condition中变成了\n,如图
我们再次将后缀改为xml之后查看我们的条件:
解决方式:
将condition前面后面的空格删掉即可;
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~