4 环境准备
4.1 三个环境
第一个环境:没有加入工作流采购系统
作用:主要学习业务流程和springmvc+mybatis
第二个环境:activiti测试环境
作用:用于测试activiti的api,提供各种service接口。
需要创建一个数据库:
仅仅有activiti的数据表
第三个环境:activiti应用环境,加入工作流的采购系统
需要创建一个数据库:
包括activiti的数据表和业务表(采购系统的表)
4.2 开发环境
4.2.1 Java环境
Jdk1.7
4.2.2 数据库
Mysql 5.1
4.2.3 Web容器
tomcat
4.2.4 开发工具
Mysql 客户端连接工具,Sqlyog或其它
文本编辑器EditPlus或其它
Java开发工具:限定为eclipse-indigo
注意:activiti的流程定义工具插件目前只支持两个版本的eclipse:Indigo 和 Juno,本教程使用indigo
4.3 Activiti环境
Activiti5.14默认支持mybatis3.2.2(替换为mybatis3.2.3)
默认支持spring3.2.2(替换为3.1.4)
参考:\jar包\activiti核心jar包及依赖包
4.3.1 下载activiti5.14
Activiti下载地址:http://activiti.org/download.html
下载activiti5.14版本,解压:
1) Database:
activiti运行需要有数据库的支持,支持的数据库有:h2, mysql, oracle, postgres, mssql, db2等,该目录存放activiti的建表脚本。
2) Docs
Activiti的帮助文档。
3) Libs
Activiti所需要的jar 包
4) Wars
官方自带的示例工程。
4.3.2 Activiti Designer流程设计器
本教程使用Activiti –Designer-eclipse-plugin(activiti流程设计器插件)完成流程的制作。
下面介绍了activiti designer设计器插件的安装方式,本教程使用的插件安装方式详细参考“activiti开发环境配置.docx”文档的“Eclipse插件安装”章节。
4.3.2.1 插件安装方式1
参数文档开发工具目录下的“activiti开发环境配置.docx”中“eclipse插件安装”,其中包括了Activiti插件。
4.3.2.2 插件安装方式2
网络在线安装:
1) 打开 Help -> Install New Software. 在如下面板中:
1) 在如下Install界面板中,点击Add按钮:
配置新装插件的地址和名称
2) 然后填入下列字段
Name:Activiti BPMN 2.0 designer
Location: http://activiti.org/designer/update/
3) 回到Install界面,在面板正中列表中把所有展示出来的项目都勾上:
4) 点击复选框
在Detail部分记得选中 "Contact all updates sites.." , 因为它会检查所有当前安装所需要的插件并可以被Eclipse下载.
5) 安装完以后,点击新建工程new->Other…打开面板,如果看到下图内容:
说明安装成功了。
4.3.2.3 补充说明
打开菜单Windows->Preferences->Activiti->Save下流程图片的生成方式:
虽然流程引擎在单独部署bpmn文件时会自动生成图片,但在实际开发过程中,自动生成的图片会导致和BPMN中的坐标有出入,在实际项目中展示流程当前位置图会有问题。
所在完成以上配置后,会由我们自己来管理流程图片。在发布流程时把流程规则文件和流程图片一起上传就行了。
4.3.3 Activiti支持的数据库
Activiti的运行需要数据库支撑,需要安装activiti数据库,支持如下版本:
4.3.4 创建mysql数据库
本教程使用mysql数据库。
创建mysql数据库activiti(名字任意):
CREATE DATABASE activiti DEFAULT CHARACTER SET utf8;
4.3.5 创建表方式1
可通过官方提供的数据库脚本创建表
进入activiti5.14下database目录:
Create目录存放了数据库创建脚本
Drop目录存放了数据库删除脚本
Upgrade目录存放了数据库升级脚本
手动执行Create目录的建库脚本即可完成数据库的创建。
(本教程采用下边介绍的程序创建数据库方式)
4.3.6 创建表方式2
通过运行java程序创建表。
4.3.6.1 创建java工程
使用eclipse创建java工程。
4.3.6.2 加入jar包
首先需要在java工程中加入ProcessEngine所需要的jar包,包括:
1) activiti-engine-5.14.jar
2) activiti依赖的jar包:mybatis、alf4j、log4j等
3) activiti依赖的spring包
4) 数据库驱动
5) 第三方数据连接池dbcp
6) 单元测试Junit-4.11.jar和hamcrest-core-1.3.jar
说明:
l activiti核心jar包及依赖包:
是activiti独立运行所需要的jar包。
比“spring+mybatis+activiti完整jar包”少了spring的aop、tx、jdbc等jar包。
l spring+mybatis+activiti完整jar包:
包括了spring所有的jar包及activiti的jar,实际使用activiti时要将activiti和业务系统整合运行,所以这里我们选用此包。
4.3.6.3 log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
4.3.6.4 activiti.cfg.xml
在classpath下创建activiti.cgf.xml文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">
</beans>
在activiti.cfg.xml中配置数据源和processEngineConfiguration
1) 数据源
<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="mysql" />
<property name="maxActive" value="3" />
<property name="maxIdle" value="1" />
</bean>
2) processEngineConfiguration
processEngineConfiguration用来创建ProcessEngine,在创建ProcessEngine时会执行数据库的操作。
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- activiti数据库表处理策略 -->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
关于processEngineConfiguration中的databaseSchemaUpdate参数,通过此参数设计activiti数据表的处理策略,参数如下:
false(默认):检查数据库表的版本和依赖库的版本, 如果版本不匹配就抛出异常。
true: 构建流程引擎时,执行检查,如果需要就执行更新。 如果表不存在,就创建。
create-drop: 构建流程引擎时创建数据库表, 关闭流程引擎时删除这些表。
drop-create:先删除表再创建表。
create: 构建流程引擎时创建数据库表, 关闭流程引擎时不删除这些表。
4.3.6.5 编写程序
创建ProcessEngineConfiguration,通过ProcessEngineConfiguration创建ProcessEngine,在创建ProcessEngine时会自动创建数据库。
//创建ProcessEngineConfiguration
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml")
//通过ProcessEngineConfiguration创建ProcessEngine,此时会创建数据库
ProcessEngine processEngine = configuration.buildProcessEngine();
System.out.println(processEngine);
说明:
1、运行以上程序段即可完成activiti数据库创建,通过改变activiti.cfg.xml中
databaseSchemaUpdate参数的值执行不同的数据表处理策略。
2、上边的方法createProcessEngineConfigurationFromResource在执行时在activiti.cfg.xml中找固定的名称processEngineConfiguration
也可以使用重载方法调用,这时可以不用限定processEngineConfiguration名称
4.3.7 数据库表的命名规则
Activiti的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。
· ACT_RE_*: 'RE'表示repository
。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
· ACT_RU_*: 'RU'表示runtime
。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
· ACT_ID_*: 'ID'表示identity
。 这些表包含身份信息,比如用户,组等等。
· ACT_HI_*: 'HI'表示history
。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
· ACT_GE_*: GE表示general。通用
数据, 用于不同场景下。
5 Activiti服务架构图
5.1 activiti.cfg.xml
activiti的引擎配置文件,包括:ProcessEngineConfiguration的定义、数据源定义、事务管理器等,此文件其实就是一个spring配置文件,下面是一个基本的配置只配置了ProcessEngineConfiguration和数据源:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.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="mysql" />
</bean>
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 数据库策略 -->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
5.2 ProcessEngineConfiguration:
流程引擎的配置类,通过ProcessEngineConfiguration可以创建工作流引擎ProceccEngine,常用的两种方法如下:
5.2.1 StandaloneProcessEngineConfiguration
通过org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration
Activiti可以单独运行,使用它创建的ProcessEngine,Activiti会自己处理事务。
配置文件方式:
通常在activiti.cfg.xml配置文件中定义一个id为 processEngineConfiguration 的bean,这里会使用spring的依赖注入来构建引擎。
方法如下:
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 数据库策略 -->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
5.2.2 SpringProcessEngineConfiguration
通过org.activiti.spring.SpringProcessEngineConfiguration 与Spring整合。
创建spring与activiti的整合配置文件:
activity-spring.cfg.xml(名称不固定)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">
<!-- 工作流引擎配置bean -->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 使用spring事务管理器 -->
<property name="transactionManager" ref="transactionManager" />
<!-- 数据库策略 -->
<property name="databaseSchemaUpdate" value="drop-create" />
<!-- activiti的定时任务关闭 -->
<property name="jobExecutorActivate" value="false" />
</bean>
<!-- 流程引擎 -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<!-- 资源服务service -->
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService" />
<!-- 流程运行service -->
<bean id="runtimeService" factory-bean="processEngine"
factory-method="getRuntimeService" />
<!-- 任务管理service -->
<bean id="taskService" factory-bean="processEngine"
factory-method="getTaskService" />
<!-- 历史管理service -->
<bean id="historyService" factory-bean="processEngine"
factory-method="getHistoryService" />
<!-- 用户管理service -->
<bean id="identityService" factory-bean="processEngine"
factory-method="getIdentityService" />
<!-- 引擎管理service -->
<bean id="managementService" factory-bean="processEngine"
factory-method="getManagementService" />
<!-- 数据源 -->
<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="mysql" />
<property name="maxActive" value="3" />
<property name="maxIdle" value="1" />
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 切面,根据具体项目修改切点配置 -->
<aop:config proxy-target-class="true">
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* cn.itcast.purchasing.service.impl.*.*(..))" />
</aop:config>
</beans>
5.2.3 创建processEngineConfiguration
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti.cfg.xml")
上边的代码要求activiti.cfg.xml中必须有一个processEngineConfiguration的bean
也可以使用下边的方法,更改bean 的名字:
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource(String resource, String beanName);
5.3 ProcessEngine:
工作流引擎,相当于一个门面接口,通过ProcessEngineConfiguration创建processEngine,通过ProcessEngine创建各各service接口。
5.3.1 一般创建方式:
//通过ProcessEngineConfiguration创建ProcessEngine
ProcessEngine processEngine =
processEngineConfiguration.buildProcessEngine();
5.3.2 简单创建方式
将activiti.cfg.xml文件名及路径固定,且activiti.cfg.xml文件中有 processEngineConfiguration的配置, 可以使用如下代码创建processEngine:
//使用classpath下的activiti.cfg.xml中的配置创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
5.4 Service :
5.4.1 Service创建方式
通过ProcessEngine创建Service,Service是工作流引擎提供用于进行工作流部署、执行、管理的服务接口。
方式如下:
RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
……
5.4.2 Service总览
RepositoryService | activiti的资源管理类 |
RuntimeService | activiti的流程运行管理类 |
TaskService | activiti的任务管理类 |
HistoryService | activiti的历史管理类 |
IdentityService | activiti的用户身份管理类 |
FormService | activiti的表单管理类 |
ManagerService | activiti的引擎管理类 |
5.4.3 RepositoryService
是activiti的资源管理类,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工具设计的业务流程图需要使用此service将流程定义文件的内容部署到计算机。
除了部署流程定义以外还可以:
查询引擎中的发布包和流程定义。
暂停或激活发布包,对应全部和特定流程定义。 暂停意味着它们不能再执行任何操作了,激活是对应的反向操作。
获得多种资源,像是包含在发布包里的文件, 或引擎自动生成的流程图。
获得流程定义的pojo版本, 可以用来通过java解析流程,而不必通过xml。
5.4.4 RuntimeService
它是activiti的流程运行管理类。可以从这个服务类中获取很多关于流程执行相关的信息
5.4.5 TaskService
是activiti的任务管理类。可以从这个类中获取任务的信息。
5.4.6 HistoryService
是activiti的历史管理类,可以查询历史信息,执行流程时,引擎会保存很多数据(根据配置),比如流程实例启动时间,任务的参与者, 完成任务的时间,每个流程实例的执行路径,等等。 这个服务主要通过查询功能来获得这些数据。
5.4.7 IdentityService
是activiti的用户管理类,它可以管理(创建,更新,删除,查询...)群组和用户。
5.4.8 FormService
是activiti的表单管理类,一个可选服务。即使不使用它,Activiti也可以完美运行, 不会损失任何功能。这个服务提供了启动表单和任务表单两个概念。 启动表单会在流程实例启动之前展示给用户, 任务表单会在用户完成任务时展示
5.4.9 ManagementService
是activiti的引擎管理类,提供了对 Activiti 流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于 Activiti 系统的日常维护。
6 Activiti入门体验
6.1 流程定义
6.1.1 Activiti-Designer使用
6.1.1.1 Palette(画板)
在eclipse或idea中安装activiti-designer/actiBPM插件即可在eclipse中使用,画板中包括以下结点:
Connection—连接
Event---事件
Task---任务
Gateway---网关
Container—容器
Boundary event—边界事件
Intermediate event- -中间事件
流程图设计完毕保存生成.bpmn文件。
6.1.1.2 新建流程
首先选中存放图形的目录,点击菜单:File—》new—》Other
创建成功:
左侧区域是绘图区,右侧区域是palette画板区域
鼠标先点击画板的元素即可在左侧绘图。
6.1.2 绘制流程

图形绘制好后会生成两个文件:
自动生成图形,需要设置eclipse:
指定流程定义key
流程定义key即流程定义的标识,在eclipse中通过properties视图查看流程的key
建议:相同的业务流程,流程定义的key名字定义一样,比如采购流程定义为purchasingflow,后期如果再修改采购流程,流程定义key仍然为purchasingflow,如果需要创建新的业务流程,比如请假流程则使用新的key。
如果properties视图没有显示需要在eclipse中打开:
6.1.4 指定任务负责人
在properties视图指定每个任务结点的负责人,
比如下边是指定部门经理审核的负责人为lisi
6.2 部署流程定义
部署流程定义就是要将上边绘制的图形即流程定义(.bpmn)部署在工作流程引擎activiti中,方法如下:
使用ProcessEngine创建RepositoryService,代码如下:
// 获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
//部署对象
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("diagram/test/purchasingflow01.bpmn")// bpmn文件
.addClasspathResource("diagram/test/purchasingflow01.png")// 图片文件
.name("企业采购流程")
.deploy();
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
执行此操作后activiti会将上边代码中指定的bpm文件和图片文件保存在activiti数据库。
6.3 启动一个流程实例
流程定义部署在activiti后就可以通过工作流管理业务流程了,也就是说上边部署的采购流程可以使用了。
针对该采购流程,启动一个流程表示发起一个新的采购单,这就相当于java类与java对象的关系,类定义好后需要new创建一个对象使用,当然可以new多个对象。对于采购流程,张三发起一个采购单需要启动一个流程实例,李四发起一个采购单也需要启动一个流程实例。
代码如下:
// 启动一个流程实例
@Test
public void startProcessInstance() {
// 获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根据流程定义key启动流程
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("purchasingflow01");
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("当前活动Id:" + processInstance.getActivityId());
}
6.4 任务查询
流程启动后,各各任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。
// 查询当前个人待执行的任务
@Test
public void findPersonalTaskList() {
// 任务负责人
String assignee = "zhangsan";
// 创建TaskService
TaskService taskService = processEngine.getTaskService();
List<Task> list = taskService.createTaskQuery()//
.processDefinitionKey("purchasingflow01")//
.taskAssignee(assignee)//只查询该任务负责人的任务
.list();
for (Task task : list) {
System.out.println("流程实例id:" + task.getProcessInstanceId());
System.out.println("任务id:" + task.getId());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务名称:" + task.getName());
}
}
6.5 任务处理
任务负责人查询待办任务,选择任务进行处理,完成任务。
// 完成任务
@Test
public void completTask() {
//任务id
String taskId = "8305";
// 创建TaskService
TaskService taskService = processEngine.getTaskService();
//完成任务
taskService.complete(taskId);
System.out.println("完成任务id="+taskId);
}
7 流程定义
7.1 流程定义
使用activiti-explorer(web控制台)或activiti-eclipse-designer插件对业务流程进行建模,这两种方式都遵循bpmn2.0标准。本教程使用activiti-eclipse-designer插件完成流程建模。
使用designer设计器绘制流程,会生成两个文件:.bpmn和.png
7.1.1 .bpmn文件
使用activiti-desinger设计业务流程,会生成.bpmn文件,
选择XML editor查询方式:
.bpmn内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<!-- 流程定义部分 -->
<process id="myProcess" name="My process" isExecutable="true">
</process>
<!-- 流程布局定义 -->
<bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
<bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
BPMN 2.0根节点是definitions节点。 这个元素中,可以定义多个流程定义(不过我们建议每个文件只包含一个流程定义, 可以简化开发过程中的维护难度)。 注意,definitions元素 最少也要包含xmlns 和targetNamespace的声明。 targetNamespace可以是任意值,它用来对流程实例进行分类。
流程定义部分:定义了流程每个结点的描述及结点之间的流程流转。
流程布局定义:定义流程每个结点在流程图上的位置坐标等信息。
7.1.2 .png图片文件
流程图片生成的两种方式:
l 使用activiti-designer设计流程图时自动生成
需在eclipse中进行配置:
使用designer设计流程图的同时自动生成与bpmn文件同名的图片文件(.png)
l 由activiti自动生成图形
流程图设计完毕向activiti中部署流程定义文件bpmn,部署时由activiti自动生成流程图片。注意:此方法生成时如果图形中有中文,生成的图片上显示乱码,且.bpmn中的坐标和图片显示错位。
7.2 流程定义部署
7.2.1 单个文件部署方式
分别将bpmn文件和png图片文件部署。
@Test
public void deployProcess() {
// 获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
// bpmn输入流
InputStream inputStream_bpmn = this
.getClass()
.getClassLoader()
.getResourceAsStream(
"cn/itcast/activiti/first/diagram/purchasing/purchasingflow01.bpmn");
// 图片输入流
InputStream inputStream_png = this
.getClass()
.getClassLoader()
.getResourceAsStream(
"cn/itcast/activiti/first/diagram/purchasing/purchasingflow01.png");
// 流程部署对象
Deployment deployment = repositoryService.createDeployment()
.addInputStream("purchasingflow01.bpmn", inputStream_bpmn)
.addInputStream("purchasingflow01.png", inputStream_png)
.deploy();
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
执行此操作后activiti会将上边代码中指定的bpm文件和图片文件保存在activiti数据库。
7.2.2 压缩包部署方式
将purchasingflow01.bpmn和purchasingflow01.png压缩成zip包。
@Test
public void deployProcessByZip() {
// 定义zip输入流
InputStream inputStream = this
.getClass()
.getClassLoader()
.getResourceAsStream(
"cn/itcast/activiti/first/diagram/purchasing/purchasingflow01.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
// 流程部署
Deployment deployment = repositoryService.createDeployment()//
.addZipInputStream(zipInputStream)//
.deploy();
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
执行此操作后activiti会将上边代码中指定的bpm文件和图片文件保存在activiti数据库。
7.2.3 操作数据表
流程定义部署后操作activiti数据表如下:
SELECT * FROM act_re_deployment #流程定义部署表,记录流程部署信息
SELECT * FROM act_re_procdef #流程定义表,记录流程定义信息
SELECT * FROM act_ge_bytearray #资源表
说明:
act_re_deployment和act_re_procdef一对多关系,一次部署在流程部署表生成一条记录,但一次部署可以部署多个流程定义,每个流程定义在流程定义表生成一条记录。每一个流程定义在act_ge_bytearray会存在两个资源记录,bpmn和png。
建议:一次部署一个流程,这样部署表和流程定义表是一对一关系,方便读取流程部署及流程定义信息。
7.3 流程定义查询
查询部署的流程定义。
// 流程定义查询
@Test
public void queryProceccDefinition() {
// 流程定义key
String processDefinitionKey = "purchasingflow01";
// 获取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());
}
}
7.4 流程定义删除
删除已经部署成功的流程定义。
public void deleteDeployment() {
// 流程部署id
String deploymentId = "8801";
// 通过流程引擎获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
//删除流程定义,如果该流程定义已有流程实例启动则删除时出错
repositoryService.deleteDeployment(deploymentId);
//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式,如果流程
//repositoryService.deleteDeployment(deploymentId, true);
}
说明:
1) 使用repositoryService删除流程定义
2) 如果该流程定义下没有正在运行的流程,则可以用普通删除。
3) 如果该流程定义下存在已经运行的流程,使用普通删除报错,可用级联删除方法将流程及相关记录全部删除。项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。
7.5 流程定义资源查询
7.5.1 方式1
通过流程定义对象获取流程定义资源,获取bpmn和png。
@Test
public void getProcessResources() throws IOException {
// 流程定义id
String processDefinitionId = "";
// 获取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);
}
}
7.5.2 方式2
通过查询流程部署信息获取流程定义资源。
// 获取流程定义图片资源
@Test
public void getProcessResources() throws IOException {
//流程部署id
String deploymentId = "9001";
// 通过流程引擎获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
//读取资源名称
List<String> resources = repositoryService.getDeploymentResourceNames(deploymentId);
String resource_image = null;
//获取图片
for(String resource_name :resources){
if(resource_name.indexOf(".png")>=0){
resource_image = resource_name;
}
}
//图片输入流
InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resource_image);
File exportFile = new File("d:/purchasingflow.png");
FileOutputStream fileOutputStream = new FileOutputStream(exportFile);
byte[] buffer = new byte[1024];
int len = -1;
//输出图片
while((len = inputStream.read(buffer))!=-1){
fileOutputStream.write(buffer, 0, len);
}
inputStream.close();
fileOutputStream.close();
}
说明:
1) deploymentId为流程部署ID
2) resource_name为act_ge_bytearray表中NAME_列的值
3) 使用repositoryService的getDeploymentResourceNames方法可以获取指定部署下得所有文件的名称
4) 使用repositoryService的getResourceAsStream方法传入部署ID和资源图片名称可以获取部署下指定名称文件的输入流
5) 最后的将输入流中的图片资源进行输出。
点关注,不迷路
文章每周持续更新,可以微信搜索「 十分钟学编程 」第一时间阅读和催更,如果这个文章写得还不错,觉得有点东西的话 ~求点赞👍 求关注❤️ 求分享❤️
各位的支持和认可,就是我创作的最大动力,我们下篇文章见!