activiti7 工作流——基础篇

该笔记是看黑马程序员课程,自己跟着敲记录的,可以去下载老师的笔记更全
百度网盘地址: https://pan.baidu.com/s/1rii67cdsIt_Y9p1lWQCcJg 提取码:506g

目录

一、activiti理解

工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。

一个软件系统中具有工作流的功能,我们把它称为工作流系统,一个系统中工作流的功能是什么?就是对系统的业务流程进行自动化管理,所以工作流是建立在业务流程的基础上,所以一个软件的系统核心根本上还是系统的业务流程,工作流只是协助进行业务流程管理。即使没有工作流业务系统也可以开发运行,只不过有了工作流可以更好的管理业务流程,提高系统的可扩展性。

用BPMN的符号来定义我们的流程,定义好后的流程,可以用activiti提供的接口来简化开发。

二、开发准备

1、idea安装activiti插件

安装插件 actiBPM
1、在idea搜不到这个插件,直接去官网
链接: https://plugins.jetbrains.com/plugin/7429-actibpm/versions
activiti7 工作流——基础篇
2、idea从文件夹安装下载的插件jar包
activiti7 工作流——基础篇

三、java开发、理解部分

1、activiti环境

1)、引入activiti相关依赖

		<dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>
        <!--  bpmn 模型处理-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>
        <!--  bpmn json数据转换-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>
        <!--   bpmn 布局-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>
        <!--   activiti云支持-->
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>

2)、activiti配置文件

在resources下创建activiti.cfg.xml文件,用于生成activiti表
注意要有mysql的相关依赖,才能连接

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    在默认方式下 bean的id 固定为processEngineConfiguration-->
    <bean id="processEngineConfiguration"
          class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!--        配置数据库相关信息-->
<!--        数据库驱动-->
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<!--        数据库连接-->
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false&amp;serverTimezone=UTC&amp;nullCatalogMeansCurrent=true" />
<!--        数据库账号密码-->
        <property name="jdbcUsername" value="root" />
        <property name="jdbcPassword" value="123456" />
<!--        activiti:数据库在生成时的策略  true:如果数据库中已经存在相应的表,要么直接使用,如果不存在,会创建-->
        <property name="databaseSchemaUpdate" value="true" />
    </bean>
</beans>

3)、activiti工具类生成25张表

	public static void main(String[] args) {
		// 需要使用activiti提供的工具类 ProcessEngine,使用getDefaultProcessEngine方法
		// getDefaultProcessEngine会默认从resource底下读取名字为activiti.cfg.xml
		ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
		System.out.println("defaultProcessEngine = " + defaultProcessEngine);
	}

遇到报Cause: java.sql.SQLSyntaxErrorException: Table ‘myactiviti.act_ge_property’ doesn’t exist错的,在数据库url加上nullCatalogMeansCurrent=true
.
url:
jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&nullCatalogMeansCurrent=true

activiti7 工作流——基础篇

4)、理解activiti表

_ge : general 通用表,用在各种情况下

_hi : history 历史记录,保存的都是历史数据,比如执行过的流程实例、变量、任务,等等。Activit默认提供了4种历史级别

_re : repository 仓库,保存一些‘静态’信息,如流程定义和流程资源(如图片、规则等)

_ru : runtime 运行时,保存一些流程实例、用户任务、变量等的运行时数据。Activiti只保存流程实例在执行过程中的运行时数据,并且当流程结束后会立即移除这些数据,这是为了保证运行时表尽量的小并运行的足够快;

表分类 表名称 表含义
. act_evt_log 事件处理日志表
一般数据 act_ge_bytearray 通用的流程定义和流程资源
. act_ge_property 系统相关属性
流程历史记录 act_hi_actinst 历史的流程实例
. act_hi_attachment 历史的流程附件
. act_hi_comment 历史的说明性信息
. act_hi_detail 历史的流程运行中的细节信息
. act_hi_identitylink 历史的流程运行过程中用户关系
. act_hi_procinst 历史的流程实例
. act_hi_varinst 历史的流程运行中的变量信息
用户用户组表 act_procdef_info 死信任务
流程定义表 act_re_deployment 部署单元信息
. act_re_model 模型信息
. act_re_procdef 已部署的流程定义
运行实例表 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 运行时变量表

2、activiti类关系图

1)、类关系图

activiti7 工作流——基础篇
新版IdentityService,FormService两个Serivce都已经删除了

2)、工作流引擎创建

1、默认方式

ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println("defaultProcessEngine = " + defaultProcessEngine);

2、一般创建方式

//先构建ProcessEngineConfiguration
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
// 通过ProcessEngineConfiguration创建ProcessEngine,此时会创建数据库
ProcessEngine processEngine = configuration.buildProcessEngine();

3)、Service服务接口

1、Service创建方式

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();

2、Service总览

service名称 service作用
RepositoryService activiti的资源管理类 : 流程仓库服务,管理流程仓库,比如部署、删除、读取流程资源
RuntimeService activiti的流程运行管理类 : 运行服务,处理所有正在运行态的流程实例、任务等。
TaskService activiti的任务管理类 : 任务服务,管理(签收、办理、指派等)、查询任务。
HistoryService activiti的历史管理类 : 历史服务,管理所有历史数据
ManagerService activiti的引擎管理类 : 引擎管理服务,和具体业务无关,管理引擎。

3、activiti入门、操作

创建activiti工作流主要包含以下几步:
1、定义流程,按照BPMN的规范,使用流程定义工具,用流程符号把整个流程描述出来
2、部署流程,把画好的流程定义成文件,加载到数据库中,生成表的数据
3、启动流程,使用java代码操作数据库表中的内容

1)、流程符号

activiti7 工作流——基础篇
排他网关(x)

只有一条路径会被选择。流程执行到该网关时,按照输出流的顺序逐个计算,当条件的计算结果为true时,继续执行当前网关的输出流;

如果多条线路计算结果都是true,则会执行第一个值为true的线路。如果所有网关计算结果没有true,则引擎会抛出异常。

排他网关需要和条件顺序流结合使用,default属性指定默认顺序流,当所有的条件不满足时会执行默认顺序流

并行网关(+)

所有路径会被同时选择
.
拆分-----并行执行所有输出顺序流,为每一条顺序流创建一个并行执行线路
.
合并-----所有从并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行

包容网关(+)

可以同时执行多条线路,也可以在网关上设置条件
.
拆分----计算每条线路上的表达式,当表达式计算结果为true时,创建一个并行线路并继续执行。
.
合并----所有从并行网关拆分并执行完成的线路均在此等候,直到所有的线路都执行完成才继续向下执行

事件网关(+)

专门为中间捕获事件设置的,允许设置多个输出流指向多个不同的中间捕获事件。当流程执行到事件网关后,流程处于等待状态,需要等待抛出事件才能将等待状态转换为活动状态。

activiti7 工作流——基础篇

2)、actiBPM使用

1、new–>bpmn文件
activiti7 工作流——基础篇

2、双击文件打开视图
3、拉取一个开始事件

4、再拉取Usertask,并取名Name、和受让人Assignee (Assignee 受让人:很重要,后面需要用这个查询这个人的任务列表)
activiti7 工作流——基础篇

5、再创建一个经理审批,并取名Name、和受让人Assignee
activiti7 工作流——基础篇

6、结束
流程可以自己设多一点,这里只做最简单的展示
activiti7 工作流——基础篇

7、流向
点住中间往下拖
activiti7 工作流——基础篇

8、点击空白,为流程指定keyname (很重要,后面的流程需要这个key当参数去查这个流程)
activiti7 工作流——基础篇

9、导出Png图片

拷贝一份bpmn文件,修改后缀名为.xml
右键查看视图,如果没有Diagrams,点击File–>settings–>Plugins–>UML勾上,重启
activiti7 工作流——基础篇点击导出png
activiti7 工作流——基础篇

3)、解决中文乱码

activiti7 工作流——基础篇activiti7 工作流——基础篇还有c盘配置文件也加上
activiti7 工作流——基础篇

-Dfile.encoding=UTF-8

4)、流程部署实现(将定义好的流程写到数据库)

activiti7 工作流——基础篇
代码

	/**
	 * 将流程保存到数据库
	 */
	public static void main(String[] args) {
		// 1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 2、获取RespositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
		// 3、使用service进行流程的部署,定义一个流程的名字,把bpmn和png部署到数据库中
		Deployment deploy = repositoryService.createDeployment().name("出差申请") // 设置名称
				.addClasspathResource("bpmn/evection.bpmn20.xml") // 加入我们的bpmn文件
				.addClasspathResource("bpmn/evection.png")
				.deploy();
		// 4、输出部署信息
		System.out.println("流程部署id="+deploy.getId());
		System.out.println("流程部署name="+deploy.getName());
	}

看输出信息主要操作了
activiti7 工作流——基础篇
activiti7 工作流——基础篇activiti7 工作流——基础篇总操作四张表
act_ge_property —— 修改系统相关属性
act_re_procdef ——流程定义表
act_re_deployment ——流程部署表:每部署一次会增加一条记录
act_ge_bytearray ——流程资源表

5)、开启流程示例

开启这个按钮
activiti7 工作流——基础篇

刚刚部署的流程添加到了流程定义表,通过key启动流程
key就是我们在上方创建流程的第8步
activiti7 工作流——基础篇
activiti7 工作流——基础篇

	/**
	 * 开始这个流程任务
	 * @param args
	 */
	public static void main(String[] args) {

		// 1、创建ProcessEngine
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 2、获取RunTimeService
		RuntimeService runtimeService = processEngine.getRuntimeService();
		// 3、根据流程定义的id启动流程
		/**
		 * 参数1:流程定义的key
		 * 参数2:businessKey,存出差申请单的id
		 */
		ProcessInstance evection = runtimeService.startProcessInstanceByKey("evection","1001");
		// 4、输出内容
		System.out.println("流程定义id " + evection.getProcessDefinitionId());
		System.out.println("流程示例id " + evection.getId());
		System.out.println("当前活动的id " + evection.getActivityId());
	}

activiti只有流程的操作,并没有我们流程中具体的字段,如出差申请:出差时间,出差目的地等信息都没有,下一步审批的人的没有信息看,不能审批
主要操作就是在 创建流程实例时,把业务表id(businessKey)添加到activiti表
activiti7 工作流——基础篇

6)、查询个人待执行的任务

可以查出这个人有什么任务待执行,任务id
activiti7 工作流——基础篇taskAssignee(“hmb”)就是我们创建流程第4步的受让人Assignee

	/**
	 * 获取个人待执行任务
	 * @param args
	 */
public static void main(String[] args) {
		// 1、获取流程执行引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 2、获取taskService
		TaskService taskService = processEngine.getTaskService();
		// 3、根据流程key 和 任务的负责人 查询任务
		List<Task> list = taskService.createTaskQuery().processDefinitionKey("evection")  // 流程的key
				.taskAssignee("hmb")  // 要查询的负责人
				.list();// 任务集合
		// 4、输出
		for (Task task:list){
			System.out.println("流程示例id = " + task.getProcessDefinitionId());
			System.out.println("任务id = " + task.getId());
			System.out.println("任务的负责人 = " + task.getAssignee());
			System.out.println("任务的名称 = " + task.getName());
		}
	}

主要执行了这个sql
activiti7 工作流——基础篇

7)、完成个人任务

通过任务id完成任务(就是上一步查出来的待执行的任务id)

	/**
	 * 完成个人任务
	 */
	public static void main(String[] args) {
		// 获取流程引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 获取taskService
		TaskService taskService = processEngine.getTaskService();
		// 根据任务id完成任务
		taskService.complete("2505");  
	}

通过用户完成任务
就是上两布的结合

/**
	 * 完成某个人任务
	 * @param args
	 */
	public static void main(String[] args) {
		// 获取流程引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 获取taskService
		TaskService taskService = processEngine.getTaskService();
		// 获取受让人的单个任务
		Task task = taskService.createTaskQuery().processDefinitionKey("evection")
				.taskAssignee("hwt")
				.singleResult(); // 单个流程结果
		// 完成该任务
		taskService.complete(task.getId());
	}

有兴趣的可以看打印的sql去看看它操作了什么表,操作了什么

8)、zip方式流程部署

文件少的可以用add一个个部署
activiti7 工作流——基础篇但是文件多的时候,会很耗时,zip方式可以进行批量的部署

	/**
	 * zip包进行批量的部署
	 */
	public  void main(String[] args) {
		// 获取流程引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 获取repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
		// 流程部署
		InputStream inputStream = this.getClass()  // 获取这个类
								.getClassLoader()    // 获取这个工程的内容
								.getResourceAsStream("bpmn/evection.zip");  // 获取resuorces目录的资源
		// 用inputStream 构造 ZipInputStream
		ZipInputStream zipInputStream = new ZipInputStream(inputStream);
		// 使用压缩包的流进行流程的部署
		Deployment deploy = repositoryService.createDeployment()
				.addZipInputStream(zipInputStream)
				.deploy();
		System.out.println("流程部署的id = " + deploy.getId());
		System.out.println("流程部署的name = " + deploy.getName());

	}

9)、流程定义信息查询

activiti7 工作流——基础篇

	/**
	 * 查询流程定义
	 */
	public static void main(String[] args) {
		// 获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 获取repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
		// 获取processDefinitionQuery对象
		ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
		// 查询当前所有的流程定义
		// processDefinitionKey(流程定义key)
		List<ProcessDefinition> evection = processDefinitionQuery.processDefinitionKey("evection")
																.orderByProcessDefinitionVersion().desc()// 排序
																.list();// 返回list集合
		// 输出信息
		for (ProcessDefinition processDefinition:evection){
			System.out.println("流程定义id = " + processDefinition.getId());
			System.out.println("流程定义名称 = " + processDefinition.getName());
			System.out.println("流程定义key = " + processDefinition.getKey());
			System.out.println("流程定义版本 = " + processDefinition.getVersion());
			System.out.println("流程定义部署id = " + processDefinition.getDeploymentId());
		}
	}

10)、流程定义删除

就是删除流程部署时放到表里的数据。
部署id就是上一步可以查出来的

1、通过部署id删除
deleteDeployment
参数1:部署id
参数2:加true 就是级联删除,如果没加,流程没结束删除不掉

	public static void main(String[] args) {
		// 获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 获取repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
		// 通过部署id来删除流程部署信息
		repositoryService.deleteDeployment("1",true);
	}

11)、下载资源文件

下载我们部署时上传的png文件、bpmn文件等
activiti7 工作流——基础篇用到IO流工具依赖

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>
/**
	 * 下载 资源文件
	 * @param args
	 */
	public static void main(String[] args) throws IOException {
		// 获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 获取repositoryService
		RepositoryService repositoryService = processEngine.getRepositoryService();
		// 获取查询对象
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
															.processDefinitionKey("evection")
															.singleResult();
		// 通过流程定义信息,获取部署id、png的name,bpmn的name
		String deploymentId = processDefinition.getDeploymentId();
		String pngName = processDefinition.getDiagramResourceName();
		String bpmnName = processDefinition.getResourceName();
		// 通过repositoryService,传递部署id,读取资源信息(png、bpmn)
		// 获取图片的流
		InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
		// 获取bpmn的流
		InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);

		// 构造OutPutStream流
		File pngFile = new File("d:/evection.png");
		File bpmnFile = new File("d:/evection.bpmn");
		FileOutputStream pngOutputStream = new FileOutputStream(pngFile);
		FileOutputStream bpmnOutputStream = new FileOutputStream(bpmnFile);

		// 输入流、输出流的转换
		IOUtils.copy(pngInput,pngOutputStream);
		IOUtils.copy(bpmnInput,bpmnOutputStream);
		// 关闭流
		IOUtils.close();
	}

12)、查看历史记录

操作act_hi_actinst表流程的历史记录
activiti7 工作流——基础篇

/**
	 * 查看历史信息
	 */
	public static void main(String[] args) {
		// 获取引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		// 获取historyService
		HistoryService historyService = processEngine.getHistoryService();
		// 获取actinst表的查询对象
		HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
		//查询 actinst表
		instanceQuery.processInstanceId("10001");
		//	instanceQuery.processDefinitionId("evection:1:7504") 或者根据DefinitionId查
		// 增加排序操作
		instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
		// 查询所有内容
		List<HistoricActivityInstance> list = instanceQuery.list();
		for (HistoricActivityInstance his:list){
			System.out.println(his.getActivityId());
			System.out.println(his.getActivityName());
			System.out.println(his.getProcessDefinitionId());
			System.out.println(his.getProcessInstanceId());
			System.out.println("=======================");
		}
	}

13)、流程挂起与激活

业务中:
有每月最后一天不处理出差申请
或者某种原因,转正申请被暂停
需要将流程挂起,等到激活时才能继续往下走

1、挂起或激活整个流程(全部流程实例)

/**
 * 全部流程实例挂起与激活
 * suspended 暂停
 * @param args
 */
public static void main(String[] args) {
	// 1、创建ProcessEngine流程引擎
	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
	// 2、获取repositoryService
	RepositoryService repositoryService = processEngine.getRepositoryService();
	// 3、查询流程定义
	ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("evection").singleResult();
	// 4、获取当前流程定义的实例是否都挂起状态
	boolean suspended = processDefinition.isSuspended();
	// 5、获取流程定义id
	String definitionId = processDefinition.getId();
	// 如果是挂起状态,改为激活
	if (suspended){
		// 激活                                     参数1:流程定义Id  ,参数2:是否激活   ,参数3:激活时间
		repositoryService.activateProcessDefinitionById(definitionId,true,null);
	}else { // 如果是正常状态,改为挂起
		// 挂起                                   参数1:流程定义Id  ,参数2:是否暂停   ,参数3:暂停时间
		repositoryService.suspendProcessDefinitionById(definitionId,true,null);
	}
}

2、挂起或激活单个流程实例

/**
 * 全部单个流程实例挂起与激活
 * suspended 暂停
 * @param args
 */
public static void main(String[] args) {
	//        获取processEngine
	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        RuntimeService
	RuntimeService runtimeService = processEngine.getRuntimeService();
//        查询流程定义的对象
	ProcessInstance processInstance = runtimeService.
			createProcessInstanceQuery().
			processInstanceId("15001").
			singleResult();
//        得到当前流程定义的实例是否都为暂停状态
	boolean suspended = processInstance.isSuspended();
//        流程定义id
	String processDefinitionId = processInstance.getId();
//        判断是否为暂停
	if(suspended){
//         如果是暂停,可以执行激活操作 ,参数:流程定义id
		runtimeService.activateProcessInstanceById(processDefinitionId);
		System.out.println("流程定义:"+processDefinitionId+",已激活");
	}else{
//          如果是激活状态,可以暂停,参数:流程定义id
		runtimeService.suspendProcessInstanceById( processDefinitionId);
		System.out.println("流程定义:"+processDefinitionId+",已挂起");
	}
}
上一篇:3DMAX7 VRAY渲染不锈钢金属勺和碗


下一篇:Flowable实战(三)流程部署管理