Activiti笔记——学习的一个过程

1 什么是工作流?

工作流(Workflow),就是通过计算机对业务流程自动化执行管理。实现多个参与者共同完成一个业务流程,使用业务流程自动化去执行。

什么工作流系统?

具有工作流功能的系统叫做工作流系统,如果具有工作流功能,如果流程变化只需要修改流程,而不需要修改业务功能。

了解工作流系统应用行业及具体应用场景:

消费品行业,制造业,电信服务业,银证险等金融服务业,物流服务业,物业服务业,物业管理,大中型进出口贸易公司,政府事业机构,研究院所及教育服务业等,特别是大的跨国企业和集团公司


 

什么是activiti

Activiti是一个工作流引擎,引擎需要嵌入到业务系统中才可以发挥作用。通过activiti实现工作流。

将业务流程抽取成一个流程定义,流程定义按照bpmn2.0标准进行定义,activiti就会按照讲预先定义好的流程进行流程的执行,从而实现流程的自动化管理,减少系统开发由业务流程变更增加的成本。

Activiti是前身就是jbpm4(也是一个工作流引擎),Activiti中的apiservice接口和jbpm4很相似。

2.1 术语

l BPM

BPMBusiness Process Management,即业务流程管理,是一种以规范化的构造端到端的卓越业务流程为中心,以持续的提高组织业务绩效为目的的系统化方法,常见商业管理教育如EMBAMBA等均将BPM包含在内。

最早在企业提出进行业务流程管理。企业中对业务流程进行管理优化,减少企业成本。

l Bpm软件

实现了业务流程管理的软件,相当于上边说的工作流系统。

 

l Bpmn2.0(掌握)

Bpmn2.0和上边的bpm是不同的概念!!!

BPMNBusiness Process Model And Notation- 业务流程模型和符号,是由BPMIBusiness Process Management Initiative)开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。

Activiti是基于bpmn2.0标准进行流程定义,activiti在进行流程定义时,使用这些模型和符号绘制流程图。

Event 用一个圆圈表示,它是流程中运行过程中发生的事情。


活动用圆角矩形表示,一个流程由一个活动或多个活动组成


 

一个bpmn图形的例子:

Activiti如何使用?

Activiti是一个工作流引擎,通常情况下activiti需要嵌入到业务系统中运行。

 

3.1 第一步:部署activiti

工具准备时的注意事项

 

Activiti运行需要在工程中加入jar包:

 Activiti本身的jar

 Activitispring的整合jar

  依赖jar

 

创建数据库(存储流程运行的数据)。

 

3.2 第二步:使用activiti流程建模工具(activity-designer)定义业务流程(.bpmn文件)

Activiti官方提供了一个和eclipse集成插件(activity-designer),用来画流程图,使用bpmn2.0标准(定义模型和符号),画流程图过程就是流程定义的过程。

在线下画流程图。

使用Activiti视图

3.3 第三步:向activiti部署业务流程定义(.bpmn文件)

.bpmn文件(流程定义文件),让activiti识别,让activiti按照流程定义文件的内容去管理业务流程。

.bpmn文件部署到activiti的数据库中,流程定义完成了。

3.4 第四步:启动一个流程实例

流程定义完成后,如果有参者来发起一个流程,activiti可以按照.bpmn文件内容去管理流程。

比如:张三创建一个采购单表示发起了一个采购流程。李四创建一个采购单,李四也发起一个采购流程。

流程定义和流程实例关系:静态和动态,类似java类和java对象。

3.5 第五步:查询待办任务

因为现在系统的业务流程已经交给activiti管理,通过activiti就可以查询当前流程执行到哪了,当前用户需要办理什么任务了,这些activiti帮我们管理了,而不像上边需要我们在sql语句中的where条件中指定当前查询的状态值是多少。

3.6 第六步:办理任务

当前流程运行到哪了这是由activiti自动管理的,当前参与者就可以完成/办理属于他的当前任务

3.7 第七步:流程结束

当任务办理完成没有下一个任务/结点了,这个流程实例就完成了。


关于环境

第一个环境:没有加入工作流采购系统

作用:主要学习业务流程和SSH+Activiti

第二个环境:activiti测试环境

作用:用于测试activitiapi,提供各种service接口。

需要创建一个数据库:

仅仅有activiti的数据表

第三个环境:activiti应用环境,加入工作流的采购系统

需要创建一个数据库:

包括activiti的数据表和业务表(采购系统的表)

activiti测试环境

Activiti自身环境包括:activitijar包和数据库

5.1 activitijar

Activiti下载地址:http://activiti.org/download.html 

下载activiti5.14版本,

解压:

1) Database

activiti运行需要有数据库的支持,支持的数据库有:h2, mysql, oracle, postgres, mssql, db2等,该目录存放activiti的建表脚本。

2) Docs

Activiti的帮助文档。

参考

中文的说明文档(activiti各各apiservice

3) Libs

Activiti所需要的jar

源码:

核心包:

activiti-engine-5.14.jar

spring整合包:

activiti-spring-5.14.jar

4) Wars

官方自带的示例工程。

 

5.2 Activiti Designer流程设计器

用于进行流程定义,按照bpmn2.0标准画流程图。

eclipse-juno版本中安装activiti designer设计器:

参数文档开发工具目录下的activiti开发环境配置.docx”中“eclipse插件安装”,其中包括了Activiti插件。

流程图画好后,生成一个.bpmn的文件(内容遵循bpmn2.0标准),通过插件可以同时生成一个png图片(流程图)。

Activiti的设计器插件安装后:

打开菜单Windows->Preferences->Activiti->Save下流程图片的生成方式:

5.3 Activiti的数据库


本教程使用mysql数据库

使用mysql5.1版本。

5.3.1 创建一个用于activiti测试的数据库

 

5.3.2 创建数据库表

方式1:从下载activiti5.14目录/database中执行sql脚本

方法2:通过java程序

5.4 通过java程序创建数据库

创建数据库思路:

Activiti运行需要核心门面接口ProcessEngine,在创建processEngine时自动检查数据库环境,可以通过数据库操作策略操作数据库。

5.4.1 第一步:创建一个java 工程

这是第二个环境,测试activiti

5.4.2 第二步:加入jar

上边是activiti单独运行的jar

下边是activitispring整合的jar,比上边目录多了springjar包:txspringmvc。。。

使用activitispring整合的jar

5.4.3 第三步:log4j.properties

5.4.4 第四步:activiti.cfg.xml

Activiti的全局配置文件,是spring的配置文件。

如果和spring没有整合时,配置数据源processEngineConfiguration

数据源:使用dbcp第三方连接池

processEngineConfiguration:用于创建processEngine

Activiti通过spring容器在创建processEngineConfiguration

数据库操作策略:

false(默认):检查数据库表的版本和依赖库的版本, 如果版本不匹配就抛出异常。

true: 构建流程引擎时,执行检查,如果需要就执行更新。 如果表不存在,就创建。

create-drop: 构建流程引擎时创建数据库表, 关闭流程引擎时删除这些表。

drop-create:先删除表再创建表。

create: 构建流程引擎时创建数据库表, 关闭流程引擎时删除这些表。

 

5.4.5 第五步:编写java程序

创建一个processEngineConfiguration对象

通过processEngineConfiguration创建procesEngine对象,同时自动创建数据库表。

5.4.6 数据库创建完成,

23张表:

 

5.4.7 表的命名规则

 

Activiti的服务架构

 

6.1 架构图

根据activiti.cfg.xml创建processEngineConfiguration

通过processEngineConfiguration创建ProcessEngine

通过ProcessEngine调用getXXXXService文件得到各各Service

 

回顾:

1. 什么是工作流

2. Activiti是什么?

3. 如何使用工作流

4. 什么是BPM?什么是BPMN?

5. 操作步骤?

6. 体系结构?

6.2 Activiti.cfg.xml

6.2.1 Activiti单独运行:

activiti.cfg.xmlactiviti的核心配置文件,名称不固定。

在此文件中配置processEngineConfiguration,通过processEngineConfiguration创建processEngine

Activiti单独运行通过StandaloneProcessEngineConfiguration创建processEngine

<!-- processEngineConfiguration: 用于创建processEngine -->

<bean id="processEngineConfiguration"

class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

<!-- 数据源 -->

<property name="dataSource" ref="dataSource" />

<!-- activiti数据库表处理策略 -->

<property name="databaseSchemaUpdate" value="drop-create" />

</bean>

6.2.2 Activitispring整合

创建applicationContext-activiti.xml,在此文件配置activiti组件。

使用SpringProcessEngineConfigurationactivitispring整合。

配置:processEngineConfiguration

 

<!-- 工作流引擎配置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>

在此文件中配置processEngine

<!-- 流程引擎 -->

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">

<property name="processEngineConfiguration" ref="processEngineConfiguration" />

</bean>

配置service;

<!-- 资源服务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" />

6.3 ProcessEngine

相当于一个门面接口,通过ProcessEngineConfiguration创建processEngine,通过ProcessEngine创建各各service接口。

门面是一个设计模式,定义一个简单bean,定义属性(门面包括组件java对象),定义get/set方法,调用门面get方法获取组件。

创建方式1;

ProcessEngine processEngine = ProcessEngineConfiguration

.createProcessEngineConfigurationFromResource(resource).buildProcessEngine();

创建方式2

6.4 service

RepositoryService

activiti的资源管理类,部署流程定义、查询流程定义、删除流程定义、查看流程定义文件(.bpmn.png

RuntimeService

activiti的流程运行管理类,启动一个流程实例,查询当前运行流程

TaskService

activiti的任务管理类,查询当前待办任务,办理当前的任务

HistoryService

activiti的历史管理类,查询历史流程信息、查询历史任务信息

IdentityService

activiti的用户身份管理类,用户授权(用户信息、组信息、用户与组关系信息)

FormService

activiti的表单管理类,在流程图中配置表单数据

ManagerService

activiti的引擎管理类,监控activiti运行状态,通常用超级管理员使用

注:红色标注为常用service

通过调用ProcessEngine.getXXXService()方法:

RepositoryService repositoryService = processEngine.getRepositoryService ()

RuntimeService runtimeService = processEngine.getRuntimeService();

…..

activiti入门体验

7.1 需求:

员工创建采购单,经过部门经理、总经理、财务三级审核。业务流程图如下:

7.2 流程定义:

使用流程设计器,定义流程,生成.bpmn文件、.png文件。

打开properties视图,


流程定义的key

流程定义key用于标识符一个业务流程,针对相同的业务流程key是相同的,比如两个采购流程,由于前后修改采购流程不一样,key定义为一样,因为它就是一个采购流程。

创建采购单结点:

指定任务的办理人:


assignee中设置任务办理人。对每个userTask结点都设置assignee

自动生成流程定义文件:.bpmn,.png

7.3 部署流程定义

流程修改后,一定要重新部署流程!!!!!

将流程定义文件部署到activiti的数据库中。

使用RepositoryService进行流程定义部署。


7.4 启动流程实例

由参与者发起一个流程,使用runTimeService


7.5 查询待办任务

用户查询当前自己需要办理的任务。

使用TaskService查询当前待办任务。

7.6 办理任务

使用TaskService完成任务

流程定义

8.1 操作流程:

1、 用户在线下定义bpmn

生成bpmn文件,png不是必须要生成的,在web页面上提供一个功能查询流程定义图这个功能,activiti本身也能生成png,生成图片会中文乱码,图中结点坐标位置错乱,要提前通过eclipse插件生成png文件。

需要两个文件:.bpmn.png

2、 通过repositoryService对流程定义进行部署

8.2 部署方法

8.2.1 单个文件部署

.bpmn.png两个文件部署到activiti

代码:

数据库操作

向流程部署表写一条记录

SELECT * FROM act_re_deployment #流程部署表

向流程定义表写记录,如果一次部署多个流程需要写多条记录。

SELECT * FROM act_re_procdef #流程定义表

Id_ 流程定义id:流程定义key:版本号:流水号

Version_ 流程定义版本:流程定义key,版本号自动加1

Key_ 流程定义key:用于标识一个业务流程,不管版本是否改变,相同的业务流程使用相同的key

deployment_id_ 流程部署id

RESOURCE_NAME_ bpmn文件名称:

DGRM_RESOURCE_NAME_ png文件名称

bpmnpng写到资源表:

SELECT * FROM act_ge_bytearray #资源表

注意:流程部署表和流程定义表是一对多关系。建议一次部署只部署一个流程,方便管理。

建议使用单个文件部署部署。

8.2.2 压缩包部署

.bpmn.png两个文件压缩成zip文件,通过repositoryService进行部署

 

通过代码部署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());

}

8.3 流程定义查询

通过此功能查询本系统通过actviti管理的流程有哪些。

使用repositoryService查询流程定义,可以根据流程定义的key查询某个业务流程在activiti中的流程定义。

// 流程定义的查询

@Test

public void queryProcessDefinition() {

//流程定义的key

String processDefinitionKey = "purchasingflow";

// 使用repositoryService

RepositoryService repositoryService = processEngine

.getRepositoryService();

//流程定义查询对象

ProcessDefinitionQuery processDefinitionQuery = repositoryService

.createProcessDefinitionQuery();

//设置查询条件

processDefinitionQuery.processDefinitionKey(processDefinitionKey);

//得出查询列表

List<ProcessDefinition> list =  processDefinitionQuery.list();

for(ProcessDefinition processDefinition:list){

System.out.println("--------------------------------");

System.out.println("流程定义的id"+processDefinition.getId());

System.out.println("流程定义的名称:"+processDefinition.getName());

System.out.println("流程定义的key"+processDefinition.getKey());

System.out.println("流程部署id"+processDefinition.getDeploymentId());

System.out.println("bpmn文件名:"+processDefinition.getResourceName());

System.out.println("png文件名:"+processDefinition.getDiagramResourceName());

}

}

 

8.4 流程定义的资源文件查询

 

需求:查看activiti中流程定义的资源文件(.bpmn.png),程序员需要查看bpmnxml格式),终端用户查询图片。

 

使用repositoryService


// 流程定义资源文件查看

@Test

public void getProcessResources() throws IOException {

// 使用repositoryService

RepositoryService repositoryService = processEngine

.getRepositoryService();

// 流程定义id

String processDefinitionId = "purchasingflow:3:1104";

// 查询一个流程定义

ProcessDefinition processDefinition = repositoryService

.createProcessDefinitionQuery()

.processDefinitionId(processDefinitionId).singleResult();

String bpmn_name = processDefinition.getResourceName();

String png_name = processDefinition.getDiagramResourceName();

// 部署id,来源于流程部署表

String deploymentId = processDefinition.getDeploymentId();

// 资源文件名称

String resourceName_bpmn = bpmn_name;

String resourceName_png = png_name;

//bmpn的输入流

InputStream inputStream_bpmn = repositoryService.getResourceAsStream(deploymentId, resourceName_bpmn);

//png的输入流

InputStream inputStream_png = repositoryService.getResourceAsStream(deploymentId, resourceName_png);

//将输入流通过文件输出流写到磁盘

FileOutputStream fileOutputStream_bpmn = new FileOutputStream(new File("D:/purchasingflow.bpmn"));

FileOutputStream fileOutputStream_png = new FileOutputStream(new File("D:/purchasingflow.png"));

byte[] b = new byte[1024];

int len=-1;

while((len=inputStream_bpmn.read(b, 0, 1024))!=-1){

fileOutputStream_bpmn.write(b, 0, len);

}

while((len=inputStream_png.read(b, 0, 1024))!=-1){

fileOutputStream_png.write(b, 0, len);

}

//释放资源

inputStream_bpmn.close();

inputStream_png.close();

fileOutputStream_bpmn.close();

fileOutputStream_png.close();

}

 

8.5 流程定义删除

使用repositoryService删除

流程一但启动是不删除的,给超级管理开放级联的功能。可以暂停/激活流程的执行。

Activiti应用(部署流程定义)

流程定义变量

@Test

   public void testVariable(){

   String processDefinitionKey = ResourceBundle.getBundle("bpmnkey").getString("processDefinitionKey");

   RuntimeService runtimeService = pe.getRuntimeService();

   

   Map<String ,Object> variables = new HashMap<String,Object>();

   variables.put("time", "明天请假");

   variables.put("address", "去医院");

   variables.put("reason","因为生病了" );

   variables.put("day", 8);

   variables.put("startDay", new Date());

   

   Person person = new Person();

   person.setId(1);

   person.setName("abc");

   person.setBirthday(new Date());

   variables.put("person",person);

   runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);

   }

   

   @Test

   public void testGetVariable(){

   String processDefinitionKey = ResourceBundle.getBundle("bpmnkey").getString("processDefinitionKey");

   TaskService taskService = pe.getTaskService();

   Task task = taskService.createTaskQuery()

      .processDefinitionKey(processDefinitionKey)

      .taskAssignee("张三")

      .singleResult();

   System.out.println(taskService.getVariable(task.getId(), "reason"));

   Date startTime = (Date)taskService.getVariable(task.getId(), "startDay");

   System.out.println(startTime.toLocaleString());

   

   Person p = (Person) taskService.getVariable(task.getId(), "person");

   System.out.println(p);

   }

 

历史记录的查看

@Test

    public void testHistoric(){

    HistoryService historyService = pe.getHistoryService();

    HistoricProcessInstanceQuery hpiq = historyService.createHistoricProcessInstanceQuery();

    String processDefinitionKey = ResourceBundle.getBundle("bpmnkey").getString("processDefinitionKey");

    hpiq.processDefinitionKey(processDefinitionKey);

    List<HistoricProcessInstance> list = hpiq.list();

    for(HistoricProcessInstance hiProcessInstance :list){

    System.out.println(hiProcessInstance.getProcessDefinitionId());

    System.out.println(hiProcessInstance.getId());

    }

    }

    

    @Test

    public void testHistoric01(){

    HistoryService historyService = pe.getHistoryService();

    HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery();

    query.processInstanceId("1501");

    

    List<HistoricActivityInstance> list = query.list();

    for(HistoricActivityInstance ai :list){

    System.out.println(ai.getActivityId());

    System.out.println(ai.getActivityName());

    System.out.println(ai.getProcessDefinitionId());

    System.out.println(ai.getProcessInstanceId());

    System.out.println("==============================");

    }

    }

猜你喜欢

转载自blog.csdn.net/A_BlackMoon/article/details/79971760
今日推荐