工作流引擎Activiti
1. 什么是工作流
1.1 工作流介绍
工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。
1.2 工作流系统
什么是工作流系统
具有工作流程功能的软件系统。用于更好的管理业务流程。
适用行业,各行各业
比如,消费品行业,制造业,电信服务业,银证险等金融服务业,物流服务业,物业服务业,物业管理,大中型进出口贸易公司,政府事业机构,研究院所及教育服务业等,特别是大的跨国企业和集团公司。
具体场景,凡是涉及到业务流程的所有场景
(1) 关键业务流程:订单、报价处理、合同审核、客户电话处理、供应链管理等
(2) 行政管理类:出差申请、加班申请、请假申请、用车申请、各种办公用品申请、购买申请、日报周报等凡是原来手工流转处理的行政表单。
(3) 人事管理类:员工培训安排、绩效考评、职位变动处理、员工档案信息管理等。
(4) 财务相关类:付款请求、应收款处理、日常报销处理、出差报销、预算和计划申请等。
(5) 客户服务类:客户信息管理、客户投诉、请求处理、售后服务管理等。
1.3 工作流实现方式
1.4 工作流实现原理
Activiti牛批之处在于,它在不改变代码的前提下实现各种业务流程的管理,适用性,扩展性很优秀。
activiti通过创建流程实例引擎,可以实现不同流程的流转,通过不断读取创建的流程节点实现流程流转。
2. Activiti7概述
2.1 Activiti介绍
Activiti 是一个工作流引擎, activiti 可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言(BPMN2.0)进行定义,业务系统按照预先定义的流程进行执行,实现了业务系统的业务流程由 activiti 进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。
2.2 Activiti使用
3. Activiti环境配置
3.1 创建数据库
CREATE DATABASE activiti DEFAULT CHARACTER SET utf8;
3.2 初始化数据库表:
- 创建Maven工程

- 加入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0
modelVersion> <groupId>com.activiti.demo
groupId> <artifactId>activiti_demo
artifactId> <version>1.0-SNAPSHOT
version>
<properties> <slf4j.version>1.6.6
slf4j.version> <log4j.version>1.2.12
log4j.version>
properties> <dependencies>
<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> <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> <dependency> <groupId>org.activiti
groupId> <artifactId>activiti-json-converter
artifactId> <version>7.0.0.Beta1
version>
dependency> <dependency> <groupId>org.activiti
groupId> <artifactId>activiti-bpmn-layout
artifactId> <version>7.0.0.Beta1
version>
dependency> <dependency> <groupId>org.activiti.cloud
groupId> <artifactId>activiti-cloud-services-api
artifactId> <version>7.0.0.Beta1
version>
dependency> <dependency> <groupId>mysql
groupId> <artifactId>mysql-connector-java
artifactId> <version>5.1.40
version>
dependency> <dependency> <groupId>junit
groupId> <artifactId>junit
artifactId> <version>4.12
version>
dependency>
<dependency> <groupId>log4j
groupId> <artifactId>log4j
artifactId> <version>${log4j.version}
version>
dependency> <dependency> <groupId>org.slf4j
groupId> <artifactId>slf4j-api
artifactId> <version>${slf4j.version}
version>
dependency> <dependency> <groupId>org.slf4j
groupId> <artifactId>slf4j-log4j12
artifactId> <version>${slf4j.version}
version>
dependency>
<dependency> <groupId>org.mybatis
groupId> <artifactId>mybatis
artifactId> <version>3.4.5
version>
dependency> <dependency> <groupId>commons-dbcp
groupId> <artifactId>commons-dbcp
artifactId> <version>1.4
version>
dependency>
dependencies> <repositories> <repository> <id>alfresco
id> <name>Activiti Releases
name> <url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/
url> <releases> <enabled>true
enabled>
releases>
repository>
repositories>
project>
- 配置日志
# Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal log4j.rootCategory=debug, CONSOLE, LOGFILE # Set the enterprise logger category to FATAL and its only appender to CONSOLE. log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE # CONSOLE is set to be a ConsoleAppender using a PatternLayout. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n # LOGFILE is set to be a File appender using a PatternLayout. log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=d:/axis.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
- 配置activity.cfg.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/activiti"/> <property name="username" value="root"/> <property name="password" value=""/>
bean>
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="dataSource" ref="dataSource">
property>
<property name="databaseSchemaUpdate" value="true"/>
bean>
beans>
- 编写代码
/ * Activiti初始化25张表 * 执行的是activiti-engine-7.0.0.Beta1.jar包下对应不同内置好的sql语句 * org\activiti\db\drop\activiti.db2.drop.engine.sql * * @author zrj * @date 2020/12/29 * @since V1.0 / public class ActivitiInit {
/ * 方式一 */ @Test public void GenActivitiTables() {
// 1.创建ProcessEngineConfiguration对象。第一个参数:配置文件名称;第二个参数:processEngineConfiguration的bean的id ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource( "activiti.cfg.xml", "processEngineConfiguration" ); // 2.创建ProcessEngine对象 ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine(); // 3.输出processEngine对象 System.out.println( processEngine ); } / * 方式二 */ @Test public void GenActivitiTables2() {
//条件:1.activiti配置文件名称:activiti.cfg.xml 2.bean的id="processEngineConfiguration" ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); System.out.println( processEngine ); } }
3.3 创建数据库表
执行上边的代码。
3.4 数据库表命名规则

Activiti 的表都以 ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的 API 对应。 ACT_RE_*: 'RE'表示 repository。这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。 ACT_RU_*: 'RU'表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti 只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。 ACT_HI_*: 'HI'表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。 ACT_GE_*: 'GE'表示 general。 通用数据, 用于不同场景下
4. Activiti架构简介

5. Activiti入门案例
5.1 流程定义
什么是流程定义
流程定义是线下按照 bpmn2.0 标准去描述 业务流程,通常使用 activiti-explorer(web 控制台)或 activiti-eclipse-designer 插件对业务流程进行建模,这两种方式都遵循 bpmn2.0 标准。本教程使用activiti-eclipse-designer 插件完成流程建模。使用 designer 设计器绘制流程,会生成两个文件: .bpmn和.png
创建bpmn文件
Palette(画板)
在 eclipse 或 idea 中安装 activiti-designer 插件即可使用,画板中包括以下结点: Connection—连接 Event---事件 Task---任务 Gateway---网关 Container—容器 Boundary event—边界事件 Intermediate event- -中间事件 流程图设计完毕保存生成.bpmn 文件
5.2 部署流程
什么是流程部署
将线下定义的流程部署到 activiti 数据库中,这就是流程定义部署,通过调用 activiti 的 api 将流程定义的 bpmn 和 png 两个文件一个一个添加部署到 activiti 中,也可以将两个文件打成 zip 包进行部署。
单个文件部署方式
分别将 bpmn 文件和 png 图片文件部署
压缩包部署方式
/ * 流程定义的部署 * activiti表有哪些? * act_re_deployment 部署信息 * act_re_procdef 流程定义的一些信息 * act_ge_bytearray 流程定义的bpmn文件及png文件 * * @author zrj * @date 2020/12/29 * @since V1.0 / public class ActivitiDeployment {
/ * 方式一 * 分别将 bpmn 文件和 png 图片文件部署 */ @Test public void activitiDeploymentTest() {
//1.创建ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到RepositoryService实例 RepositoryService repositoryService = processEngine.getRepositoryService(); //3.进行部署 Deployment deployment = repositoryService.createDeployment() .addClasspathResource( "diagram/holiday.bpmn" ) .addClasspathResource( "diagram/holiday.png" ) .name( "请假申请单流程" ) .deploy(); //4.输出部署的一些信息 System.out.println( deployment.getName() ); System.out.println( deployment.getId() ); } / * 方式二 * 将 holiday.bpmn 和 holiday.png 压缩成 zip 包 */ @Test public void activitiDeploymentTest2() {
//1.创建ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到RepositoryService实例 RepositoryService repositoryService = processEngine.getRepositoryService(); //3.转化出ZipInputStream流对象 InputStream is = ActivitiDeployment.class.getClassLoader().getResourceAsStream( "diagram/holidayBPMN.zip" ); //将 inputstream流转化为ZipInputStream流 ZipInputStream zipInputStream = new ZipInputStream( is ); //3.进行部署 Deployment deployment = repositoryService.createDeployment() .addZipInputStream( zipInputStream ) .name( "请假申请单流程" ) .deploy(); //4.输出部署的一些信息 System.out.println( deployment.getName() ); System.out.println( deployment.getId() ); } }
操作数据表
-- activiti表有哪些? -- 部署信息 select * from act_re_deployment ; -- 流程定义的一些信息 select * from act_re_procdef; -- 流程定义的bpmn文件及png文件 select * from act_ge_bytearray;
5.3 启动流程
/ * 启动流程实例: * 前提是先已经完成流程定义的部署工作 * 背后影响的表: * act_hi_actinst 已完成的活动信息 * act_hi_identitylink 参与者信息 * act_hi_procinst 流程实例 * act_hi_taskinst 任务实例 * act_ru_execution 执行表 * act_ru_identitylink 参与者信息 * act_ru_task 任务 * * @author zrj * @date 2020/12/29 * @since V1.0 / public class ActivitiStartInstance {
public static void main(String[] args) {
//1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.得到RunService对象 RuntimeService runtimeService = processEngine.getRuntimeService(); //3.创建流程实例 流程定义的key需要知道 holiday ProcessInstance processInstance = runtimeService.startProcessInstanceByKey( "holiday" ); //4.输出实例的相关信息 System.out.println( "流程部署ID" + processInstance.getDeploymentId() ); System.out.println( "流程定义ID" + processInstance.getProcessDefinitionId() ); System.out.println( "流程实例ID" + processInstance.getId() ); System.out.println( "活动ID" + processInstance.getActivityId() ); } }
5.4 流程定义查询
/ * 流程定义查询 * * @author zrj * @date 2020/12/29 * @since V1.0 / public class QueryProceccDefinition {
@Test public void queryProceccDefinition() {
// 流程定义key String processDefinitionKey = "holiday"; //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); // 获取repositoryService RepositoryService repositoryService = processEngine.getRepositoryService(); // 查询流程定义 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); //遍历查询结果 List<ProcessDefinition> list = processDefinitionQuery .processDefinitionKey( processDefinitionKey ) .orderByProcessDefinitionVersion().desc().list(); for (ProcessDefinition processDefinition : list) {
System.out.println( "------------------------" ); System.out.println( " 流 程 部 署 id : " + processDefinition.getDeploymentId() ); System.out.println( "流程定义id: " + processDefinition.getId() ); System.out.println( "流程定义名称: " + processDefinition.getName() ); System.out.println( "流程定义key: " + processDefinition.getKey() ); System.out.println( "流程定义版本: " + processDefinition.getVersion() ); } } }
5.5 流程定义删除
/ * 删除指定流程id的流程 */ public void deleteDeployment() {
// 流程部署id String deploymentId = "8801"; //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); // 通过流程引擎获取repositoryService RepositoryService repositoryService = processEngine.getRepositoryService(); //删除流程定义, 如果该流程定义已有流程实例启动则删除时出错 repositoryService.deleteDeployment( deploymentId ); //设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设 //置为false非级别删除方式,如果流程 repositoryService.deleteDeployment( deploymentId, true ); }
5.6 流程定义资源查询
/ * 获取资源 */ @Test public void getProcessResources() throws IOException {
// 流程定义id String processDefinitionId = ""; //1.得到ProcessEngine对象 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); // 获取repositoryService RepositoryService repositoryService = processEngine.getRepositoryService(); // 流程定义对象 ProcessDefinition processDefinition = repositoryService .createProcessDefinitionQuery() .processDefinitionId( processDefinitionId ).singleResult(); //获取bpmn String resource_bpmn = processDefinition.getResourceName(); //获取png String resource_png = processDefinition.getDiagramResourceName(); // 资源信息 System.out.println( "bpmn: " + resource_bpmn ); System.out.println( "png: " + resource_png ); File file_png = new File( "d:/purchasingflow01.png" ); File file_bpmn = new File( "d:/purchasingflow01.bpmn" ); // 输出bpmn InputStream resourceAsStream = null; resourceAsStream = repositoryService.getResourceAsStream( processDefinition.getDeploymentId(), resource_bpmn ); FileOutputStream fileOutputStream = new FileOutputStream( file_bpmn ); byte[] b = new byte[1024]; int len = -1; while ((len = resourceAsStream.read( b, 0, 1024 )) != -1) {
fileOutputStream.write( b, 0, len ); } // 输出图片 resourceAsStream = repositoryService.getResourceAsStream( processDefinition.getDeploymentId(), resource_png ); fileOutputStream = new FileOutputStream( file_png ); // byte[] b = new byte[1024]; // int len = -1; while ((len = resourceAsStream.read( b, 0, 1024 )) != -1) {
fileOutputStream.write( b, 0, len ); } }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200030.html原文链接:https://javaforall.net
