目录
1. ProcessEngine 流程引擎(核心)
获取方法一:通过ProcessEngines
获取,默认会加载activiti.cfg.xml配置文件获取数据库连接。
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
activiti.cfg.xml主要内容如下:
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 连接数据库的配置 -->
<property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti?useUnicode=true&characterEncoding=utf8"></property>
<property name="jdbcUsername" value="root"></property>
<property name="jdbcPassword" value="root"></property>
<!-- 没有表则创建表 -->
<property name="databaseSchemaUpdate" value="true"></property>
</bean>
获取方法二:通过ProcessEngineConfiguration
获取。
ProcessEngineConfiguration cfg = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration()
.setJdbcDriver("com.mysql.jdbc.Driver")
.setJdbcUrl("jdbc:mysql://localhost:3306/db_activiti")
.setJdbcUsername("root")
.setJdbcPassword("root")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine processEngine = cfg.buildProcessEngine();
2. RepositoryService 流程存储服务
RepositoryService用于流程定义和部署模型相关。
RepositoryService repositoryService = processEngine.getRepositoryService();
创建流程模型
public void createModel() {
String name = "请假流程模型";
String key = "LEAVE-MODEL";
String metaInfo = "流程描述:" + name + ",KEY是" + key;
Model modelData = repositoryService.newModel();
modelData.setMetaInfo(metaInfo);
modelData.setName(name);
modelData.setKey(StringUtils.defaultString(key));
repositoryService.saveModel(modelData);
}
运行后会在以下表中生成数据
act_re_model
部署流程
// 方式一:通过加载diagrams下的bpmn和png文件部署
public void deploy() {
Deployment deployment = repositoryService
.createDeployment() // 创建一个部署对象
.name("一个流程名称") // 添加部署的名称
.addClasspathResource("diagrams/helloWorld.bpmn") // 从classpath的资源中加载,一次只能加载一个文件
.addClasspathResource("diagrams/helloWorld.png") // 从classpath的资源中加载,一次只能加载一个文件
.deploy(); // 完成部署
System.out.println("部署的流程信息:" + deployment);
}
// 方式二:通过加载diagrams下的zip文件部署
public void deployByZip() {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("diagrams/helloWorld.zip");
ZipInputStream zipInputStream = null;
if (inputStream != null) {
zipInputStream = new ZipInputStream(inputStream);
}
Deployment deployment = repositoryService
.createDeployment() // 创建一个部署对象
.name("一个名称") // 添加部署的名称
.addZipInputStream(zipInputStream) //指定zip格式的文件完成部署
.deploy(); // 完成部署
System.out.println("部署的流程信息:" + deployment);
}
// 方式三:通过输入流部署
public void deployByInputStream(){
InputStream inputStreambpmn = this.getClass().getResourceAsStream("/diagrams/helloWorld.bpmn");
InputStream inputStreampng = this.getClass().getResourceAsStream("/diagrams/helloWorld.png");
Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
.createDeployment()//创建一个部署对象
.name("哈喽我的")//添加部署的名称
//使用资源文件的名称(要求:与资源文件的名称要一致),和输入流完成部署
.addInputStream("helloWorld.bpmn", inputStreambpmn)
//使用资源文件的名称(要求:与资源文件的名称要一致),和输入流完成部署
.addInputStream("helloWorld.png", inputStreampng)
.deploy();//完成部署
System.out.println("部署的流程信息:" + deployment);
}
运行后会在以下表中生成数据:
act_re_deployment 部署对象表
存放流程定义的显示名和部署时间,每部署一次增加一条记录
act_re_procdef 流程定义表
存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。
注意:当流程定义的key相同的情况下,使用的是版本升级
act_ge_bytearray 资源文件表
存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录,一条是关于bpmn规则文件的,一条是图片的(如果部署时只指定了bpmn一个文件,activiti会在部署时解析bpmn文件内容自动生成流程图)。两个文件不是很大,都是以二进制形式存储在数据库中。
act_ge_property 主键生成策略表
查询部署对象
部署对象的查询主要是对act_re_deployment表的查询,activiti通过DeploymentQuery查询流程。
//创建一个部署对象的查询
DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();
DeploymentQuery类中有各种方法进行查询,这里不做列出。
查询流程定义
流程的查询主要是对act_re_procdef表的查询,activiti通过ProcessDefinitionQuery查询流程。
//创建一个流程定义的查询
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
ProcessDefinitionQuery类中有各种方法进行查询,这里不做列出。
下面列出act_re_procdef表字段的作用(注释)。
使用部署ID,删除流程定义
public void deleteProcessDefinition(){
// 部署ID
String deploymentId = "601";
/*
* 不带级联的删除
* 只能删除没有启动的流程,如果流程启动,就会抛出异常
*/
repositoryService.deleteDeployment(deploymentId);
/*
* 级联删除
* 不管流程是否启动,都能可以删除
*/
repositoryService.deleteDeployment(deploymentId, true);
}
如果该流程定义下没有正在运行的流程,则可以用普通删除。如果是有关联的信息,用级联删除。项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。
查看流程图
public void viewPicture(HttpServletResponse response) throws IOException {
String deploymentId = "801"; // 部署ID
String resourceName = ""; // 图片资源名称
List<String> list = repositoryService.getDeploymentResourceNames(deploymentId);
if(list!=null && list.size()>0){
for(String name:list){
if(name.contains(".png")){
resourceName = name;
break;
}
}
}
//获取图片的输入流
InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
ServletOutputStream outputStream = response.getOutputStream();
for (int b = -1; (b = inputStream.read()) != -1;) {
outputStream.write(b);
}
outputStream.close();
inputStream.close();
}
resourceName为act_ge_bytearray表中NAME_列的值
3. RuntimeService 流程运行控制服务
与正在执行的流程实例和执行对象相关的Service
RuntimeService runtimeService = processEngine.getRuntimeService();
启动流程实例
public void start() {
/*
* key对应helloworld.bpmn文件中id的属性值,即 act_re_model 和 act_re_procdef 中的 key 值
* 之所以使用流程定义的key而不是id来启动流程实例,是因为使用key值启动默认是按照最新版本的流程定义启动
*/
String key = "helloworld";
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
System.out.println("流程实例ID:"+processInstance.getId());
System.out.println("流程定义ID:"+processInstance.getProcessDefinitionId());
}
运行后会在以下表中生成数据:
act_ru_execution 正在执行的执行对象表
如果是单例流程(没有分支和聚合),那么流程实例ID和执行对象ID是相同的。
一个流程的流程实例只能有一个,执行对象可以存在多个(如果存在分支和聚合)。
act_hi_procinst 流程实例历史表
act_ru_task 正在执行的任务表
只有节点是UserTask的时候,该表中才存在数据。(即“开始”、“结束”节点不算)
act_hi_taskinst 任务历史表
只有节点是UserTask的时候,该表中才存在数据。(即“开始”、“结束”节点不算)
act_hi_actinst 所有活动节点的历史表(包括“开始”、“结束”节点)
- 如果是单例流程,执行对象ID就是流程实例ID;
- 如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同;
- 一个流程中,流程实例只有一个,执行对象可以存在多个。
查询流程状态(判断流程是否结束)
public boolean processIsEnd(){
String processInstanceId = "1001";
ProcessInstance processInstance = runtimeService
.createProcessInstanceQuery()//创建流程实例查询
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
return processInstance == null;
}
4. TaskService 任务管理服务
与正在执行的任务相关的Service。
TaskService taskService = processEngine.getTaskService();
查询当前人的个人任务
实际上就是查询act_ru_task表的数据。
public void getMyPersonalTask() {
String assignee = "张三"; // 当前人的姓名
List<Task> taskList = taskService
.createTaskQuery() // 创建任务查询对象
.taskAssignee("") // 指定个人任务查询,指定办理人
.list();
if(taskList!=null && taskList.size()>0){
for(Task task:taskList){
System.out.println("任务ID:"+task.getId()); // 假设返回302
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("########################################################");
}
}
}
完成个人任务
public void finishMyTask() {
String taskId = "302"; //任务ID
taskService.complete(taskId);
System.out.println("完成任务,任务ID:"+taskId);
}
运行后以下表中数据会发生变化
act_ru_execution
如果流程实例没有结束,表中的ACT_ID_字段的值会改变,指向下一个节点;
如果流程实例结束,表中数据删除。
act_hi_procinst
如果流程实例没有结束,表中数据不变;
如果流程实例结束,表中END_TIME_记录完成时间。
act_ru_task
如果流程实例没有结束,表中的NAME_、ASSIGNEE_字段的值会改变,指向下一个节点;
如果流程实例结束,表中数据删除。
act_hi_taskinst
表新增一条历史记录,原历史记录END_TIME_记录完成时间。
act_hi_actinst
表新增一条历史记录,原历史记录END_TIME_记录完成时间。
5. HistoryService 任务管理服务
与历史数据相关的Service。
HistoryService historyService = processEngine.getHistoryService();
查询历史流程实例
public void findHistoryProcessInstance(){
String processInstanceId = "1001";
HistoricProcessInstance hisPI = historyService
.createHistoricProcessInstanceQuery()//创建历史流程实例查询
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
System.out.println(hisPI);
}
查询历史任务
public void findHistoryTask(){
String taskAssignee = "张三";
List<HistoricTaskInstance> list = historyService
.createHistoricTaskInstanceQuery()//创建历史任务实例查询
.taskAssignee(taskAssignee)//指定历史任务的办理人
.list();
if(list!=null && list.size()>0){
for(HistoricTaskInstance hisTask:list){
System.out.println(hisTask);
}
}
}