Activiti流程控制框架

Activiti概述

       Activiti5是由Alfresco软件发布的业务流程管理(BPM框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom BaeyensJBoss jBPM(4.4)的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务流程图。 

activitiAPI架构图

26213955_qoGb.jpg

activiti插件安装

1.解压文件

26213956_Hv0b.png

2.把压缩包中的内容放入eclipse根目录的dropins文件夹下

26213956_Wenk.png

3.重启eclipse,点击新建工程new->Other打开面板,如果看到下图内容:

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

26213958_9BzA.jpg

虽然流程引擎在单独部署bpmn文件时会自动生成图片,但在实际开发过程中,自动生成的图片会导致和BPMN中的坐标有出入,在实际项目中展示流程当前位置图会有问题。

所在完成以上配置后,会由我们自己来管理流程图片。在发布流程时把流程规则文件和流程图片一起上传就行了。

数据表介绍

Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。

1) ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。

2) ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。

3) ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。

4) ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。

5) ACT_GE_*: 通用数据, 用于不同场景下。

  • 1.资源库流程规则表

       1)   act_re_deployment 部署信息表

2) act_re_model  流程设计模型部署表

3) act_re_procdef  流程定义数据表

  • 2.运行时数据库表

1) act_ru_execution运行时流程执行实例表

2) act_ru_identitylink运行时流程人员表,主要存储任务节点与参与者的相关信息

3) act_ru_task运行时任务节点表

4) act_ru_variable运行时流程变量数据表

  • 3.历史数据库表

1) act_hi_actinst 历史节点表

2) act_hi_attachment历史附件表

3) act_hi_comment历史意见表

4) act_hi_identitylink历史流程人员表

5) act_hi_detail历史详情表,提供历史变量的查询

6) act_hi_procinst历史流程实例表

7) act_hi_taskinst历史任务实例表

8) act_hi_varinst历史变量表

  • 4.组织机构

1) act_id_group用户组信息表

2) act_id_info用户扩展信息表

3) act_id_membership用户与用户组对应信息表

4) act_id_user用户信息表

张表很常见,基本的组织机构管理,关于用户认证方面建议还是自己开发一套,组件自带的功能太简单,使用中有很多需求难以满足 

  • 5.通用数据

1) act_ge_bytearray二进制数据表

2) act_ge_property属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录

activiti.cfg.xml

Activiti核心配置文件,配置流程引擎创建工具的基本参数和数据库连接池参数。

定义数据库配置参数:

 jdbcUrl数据库的JDBC URL

 jdbcDriver对应不同数据库类型的驱动。

 jdbcUsername连接数据库的用户名。

 jdbcPassword连接数据库的密码。

基于JDBC参数配置的数据库连接 会使用默认的MyBatis连接池。 下面的参数可以用来配置连接池(来自MyBatis参数):

 jdbcMaxActiveConnections连接池中处于被使用状态的连接的最大值。默认为10

 jdbcMaxIdleConnections连接池中处于空闲状态的连接的最大值。

 jdbcMaxCheckoutTime连接被取出使用的最长时间,超过时间会被强制回收。 默认为2000020秒)。

 jdbcMaxWaitTime这是一个底层配置,让连接池可以在长时间无法获得连接时, 打印一条日志,并重新尝试获取一个连接。(避免因为错误配置导致沉默的操作失败)。 默认为2000020秒)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
     <!-- 注册一个流程控制引擎的配置文件对象 -->
     < 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:///activiti" ></ property >
         < property name = "jdbcUsername" value = "root" ></ property >
         < property name = "jdbcPassword" value = "123" ></ property >
         < property name = "databaseSchemaUpdate" value = "true" ></ property >
     </ bean >
     <!-- 创建流程控制引擎.传入流程控制引擎的配置对象 -->
     < bean id = "processEngine" class = "org.activiti.spring.ProcessEngineFactoryBean" >
         < property name = "processEngineConfiguration" ref = "processEngineConfiguration" ></ property >
     </ bean >
</ beans >

26213957_lj4x.png

  • Execution

Activiti用这个对象去描述流程执行的每一个节点。在没有并发的情况下,同ProcessInstance 

管理流程定义

说明:流程定义文档有两部分组成:

1) bpmn文件

流程规则文件。在部署后,每次系统启动时都会被解析,把内容封装成流程定义放入项目缓存中。Activiti框架结合这个xml文件自动管理流程。

2) 展示流程图的图片

在系统里需要展示流程的进展图片

  • 1.部署流程定义

部署流程定义也可以认为是增加流程定义

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

这里能直接调用方法是因为配置文件里有两个<bean>,且bean的id必须是processEngine和配置bean的id是processEngineCongiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
//获取默认的引擎,默认加载配置文件
     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
     /**
      * 部署流程引擎(增加流程引擎)
      */
     @Test
     public void demo1(){
         DeploymentBuilder deployment =processEngine.getRepositoryService().createDeployment();

        deployment.addClasspathResource("activiti.bpmn");

         deployment.addClasspathResource( "activiti.png" );
         Deployment deploy = deployment.deploy();
         System.out.println(deploy.getId());
     }

步骤:

1) 首先获得默认的流程引擎,在创建时会自动加载classpath下得activiti.cfg.xml

2) 通过流程引擎获取了一个RepositoryService对象->仓库服务对象

3) 由仓库的服务对象产生一个部署对象配置对象,用来封装部署环境的相关配置。

4) 可以看出这是一个链式编程,在部署配置对象中设置显示名,上传规则文件相对classpath的地址。

5) 部署,也是往数据库中存储流程定义的过程。

6) 这一步在数据库中将操作三张表:

a) act_re_deployment

存放流程定义的显示名和部署时间,每部署一次增加一条记录

b) act_re_procdef

存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。

c) act_ge_bytearray

存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录,一条是关于bpmn规则文件的,一条是图片的(如果部署时只指定了bpmn一个文件,activiti会在部署时解析bpmn文件内容自动生成流程图)。两个文件不是很大,都是以二进制形式存储在数据库中。

  • 2.查询流程定义信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//获取默认的引擎,默认加载配置文件
     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
     /**
      * 查询流程引擎信息
      */
     @Test
     public void demo2(){
         ProcessDefinitionQuery query = processEngine.getRepositoryService().createProcessDefinitionQuery();
         List<ProcessDefinition> list = query.list();
         for (ProcessDefinition processDefinition : list) {
             String id = processDefinition.getId(); //流程定义ID
             String key = processDefinition.getKey(); //流程定义Key
             String deploymentId = processDefinition.getDeploymentId(); //获取部署ID
             String name = processDefinition.getName(); //获取流程定义名字
             int i = processDefinition.getVersion(); //获取流程定义版本号
             String diagramResourceName = processDefinition.getDiagramResourceName(); //获取png名字
             System.out.println(id+ "--" +key+ "--" +deploymentId+ "--" +name+ "--" +i+ "--" +diagramResourceName);
         }
     }

26213958_EkLV.png

1) 因为流程定义的信息存放在仓库中,所以在第53行应该获取RepositoryService

2) 55,创建流程定义查询对象,可以在ProcessDefinitionQuery上设置查询过滤参数

3) 64,调用ProcessDefinitionQuery对象的list方法,执行查询,获得符合条件的流程定义列表

4) 由运行结果可以看出:

a) KeyName的值为:bpmn文件process节点的idname的属性值

b) key属性被用来区别不同的流程定义。

c) 带有特定key的流程定义第一次部署时,version1。之后每次部署都会在当前最高版本号上加1

d) Id的值的生成规则为:{processDefinitionKey}:{processDefinitionVersion}:{generated-id}, 这里的generated-id是一个自动生成的唯一的数字

e) 重复部署一次,deploymentId的值以一定的形式变化

f) 流程定义(ProcessDefinition)在数据库中没有相应的表对应,只是从act_ge_bytearray表中取出相应的bpmnpng图片,并进行解析。

  • 3.删除流程部署

1
2
3
4
5
6
7
8
9
10
11
12
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 删除流程定义
  */
@Test
public void demo3(){
     //删除制定的信息,如果有级联,则报错
     processEngine.getRepositoryService().deleteDeployment( "1" );
     //删除制定的信息,如果有级联,则会暴力删除所有的关联信息
     processEngine.getRepositoryService().deleteDeployment( "1" , true );
}

说明:

1) 因为删除的是流程定义,而流程定义的部署是属于仓库服务的,所以应该先得到RepositoryService

2) 如果该流程定义下没有正在运行的流程,则可以用暴力删除。如果是有关联的信息,用88行的方法进行级联删除。一般情况下用41行就可以。由于88删除涉及的数据比较多,一般只开放给超级管理员使用。

  • 4.获取流程定义文档的资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 查询流程定义文档(这里查图片)
  * @throws IOException
  */
@Test
public void demo4() throws IOException{
     List<String> names = processEngine.getRepositoryService().getDeploymentResourceNames( "1" );
     String resourceName = null ;
     //遍历资源文件名称列表
     for (String string : names) {
         //获取以.png结尾的文件名
         if (string.indexOf( ".png" )>= 0 ) {
             resourceName=string;
         }
     }
     if (resourceName!= null ) {
         File file = new File( "F:/" +resourceName);
         //通过文件部署名称和ID获取输出流
         InputStream resourceAsStream = processEngine.getRepositoryService().getResourceAsStream( "1" , resourceName);
         //工具类拷贝文件
         FileUtils.copyInputStreamToFile(resourceAsStream, file);
     }
}

26213958_ozHa.png

说明:

1) deploymentId为流程部署ID

2) resourceNameact_ge_bytearray表中NAME_列的值

3) 使用repositoryServicegetDeploymentResourceNames方法可以获取指定部署下得所有文件的名称

4) 使用repositoryServicegetResourceAsStream方法传入部署ID和文件名称可以获取部署下指定名称文件的输入流

5) 最后的有关IO流的操作,使用FileUtils工具的copyInputStreamToFile方法完成流程流程到文件的拷贝

流程实例管理

  • 1.启动流程实例

1
2
3
4
5
6
7
8
9
10
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 开启流程*实例
  */
@Test
public void demo5(){
     ProcessInstance instanceById = processEngine.getRuntimeService().startProcessInstanceById( "qjlc:1:4" );
     System.out.println(instanceById.getId());
}

26213959_Bmon.png

     1) 操作数据库的act_ru_execution,如果是用户任务节点,同时也会在act_ru_task添加一条记录

  • 2.查询个人任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 查询个人任务
  */
@Test
public void demo6(){
     //创建流程查询对象
     TaskQuery createTaskQuery = processEngine.getTaskService().createTaskQuery();
     List<Task> list = createTaskQuery
             .taskAssignee( "张三" ) //查询办理人
             .orderByTaskCreateTime() //查询创建时间
             .desc().list(); //排序
     for (Task task : list) {
         String id = task.getId();
         Date createTime = task.getCreateTime();
         String name = task.getName();
         String parentTaskId = task.getParentTaskId();
         String taskDefinitionKey = task.getTaskDefinitionKey();
         System.out.println(id+ "--" +createTime+ "--" +name+ "--" +parentTaskId+ "--" +taskDefinitionKey);
     }
}

26213958_XreR.png

说明:

1) 因为是任务查询,所以从processEngine中应该得到TaskService

2) 使用TaskService获取到任务查询对象TaskQuery

3) 为查询对象添加查询过滤条件,使用taskAssignee指定任务的候选者(即查询指定用户的代办任务),添加分页排序等过滤条件

4) 调用list方法执行查询,返回办理者为指定用户的任务列表

5) 任务ID、名称、办理人、创建时间可以从act_ru_task表中查到。

6)在这种情况下,ProcessInstance相当于Execution

7) 如果assignee属性为部门经理,结果为空。因为现在流程只到了填写请假申请阶段,后面的任务还没有执行,即在数据库中没有部门经理可以办理的任务,所以查询不到。

8) 一个Task节点和Execution节点是11的情况,在task对象中使用Execution_来标示他们之间的关系

9) 任务ID在数据库表act_ru_task中对应“ID_”列

  • 3.查询员工可接取的公共任务(有组任务的时候)

       对指定用户的可接取的公共任务执行查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
      /**
  * 查询共有任务任务
  */
@Test
public void demo7(){
     List<Task> list = processEngine.getTaskService().createTaskQuery().taskCandidateUser( "张三" ).list();
     for (Task task : list) {
         String id = task.getId();
         String name = task.getName();
         String executionId = task.getExecutionId();
         String taskDefinitionKey = task.getTaskDefinitionKey();
         System.out.println(id+ "--" +name+ "--" +executionId+ "--" +taskDefinitionKey);
     }
}

说明:

1.前面步骤类似,查询任务首先使用TaskService创建TaskQuery对象

2.在查询对象上,添加taskCandidateUser过滤条件,代表过滤任务候选者为自己的任务

3.调用list方法返回指定用户的可接任务列表

4.所有公共任务的assignee属性为空

  • 4.认领任务(将组任务变为个人任务)

通常一个任务为公共任务任务都有一个以上的候选者,用户想要办理它应该先进行认领任务操作,即把自己变成任务的拥有者。

1
2
3
4
5
6
7
8
9
10
11
12
13
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 认领任务
  */
@Test
public void demo7(){
     //任务ID
     String taskId = "104" ;
     //接手任务的员工ID
     String userId = "105" ;
     processEngine.getTaskService().claim(taskId, userId);
}

说明:

1.任务相关操作,首先得到taskService

2.确定被认领的任务ID和认领人ID

3.调用taskServiceclaim(认领)方法,把公共任务变成指定用户的私有任务

办理任务

1
2
3
4
5
6
7
8
9
10
11
12
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 办理任务
  */
@Test
public void demo8(){
     //任务ID
     String taskId = "104" ;
     //办理任务
     processEngine.getTaskService().complete(taskId);
}

说明:

1) 是办理任务,所以从ProcessEngine得到的是TaskService

2) 当执行完这段代码,再以员工的身份去执行查询的时候,会发现这个时候已经没有数据了。

3) 对于执行完的任务,activiti将从act_ru_task表中删除该任务,下一个任务会被插入进来。

4) 部门经理的身份进行查询,可以查到结果。因为流程执行到部门经理审批这个节点了。

5) 再执行办理任务代码,执行完以后以部门经理身份进行查询,没有结果。

                             6)  重复第34步直到流程执行完。

  • 验证流程已经结束

在流程执行的过程中,创建的流程实例ID在整个过程中都不会变,当流程结束后,流程实例将会被删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 验证流程是否结束
  */
@Test
public void demo9(){
     String ProcessInstanceID = "qjlc:1:4" ;
     ProcessInstance result = processEngine.getRuntimeService()
             .createProcessInstanceQuery() //创建实例查询
             .processInstanceId(ProcessInstanceID) //传入实例ID
             .singleResult(); //查询唯一结果
     if (result!= null ) {
         System.out.println( "当前执行到的节点ID是" +result.getActivityId());
     } else {
         System.out.println( "ID为" +ProcessInstanceID+ "流程执行完毕" );
     }
}

26213959_65fU.png

说明:

1) 因为是查询流程实例,所以先获取runtimeService

2) 创建流程历史查询对象,设置实例ID过滤参数

3) 由于一个流程实例ID只对应一个实例,使用singleResult执行查询返回一个唯一的结果,如果结果数量大于1,则抛出异常

                             4)判断指定ID的实例是否存在,如果结果为空,则代表流程结束,实例已被删除

流程历史

已完成的任务在act_ru_taskact_ru_execution表中都已被删除,但是这些数据还存在activiti的数据库中,作为历史改由HistoryService来管理。

历史是一个组件,它可以捕获发生在进程执行中的信息并永久的保存,与运行时数据不同的是,当流程实例运行完成之后它还会存在于数据库中。

对已成为历史的数据主要进行查询操作,我们主要关心两种类型的历史数据:

HistoricProcessInstance 包含当前和已经结束的流程实例信息。

HistoricActivityInstance 包含一个活动(流程上的节点)的执行信息 。

  • 1.查看历史活动数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 查询历史流程实例数据
  */
@Test
public void demo11(){
     HistoricActivityInstanceQuery query = processEngine.getHistoryService().createHistoricActivityInstanceQuery();
     List<HistoricActivityInstance> list = query.list();
     for (HistoricActivityInstance historicActivityInstance : list) {
         String activityId = historicActivityInstance.getActivityId(); //获取活动ID
         String activityName = historicActivityInstance.getActivityName(); //获取活动名称
         String activityType = historicActivityInstance.getActivityType(); //获取活动类型
         String assignee = historicActivityInstance.getAssignee(); //获取执行人
         Date endTime = historicActivityInstance.getEndTime(); //获取流程执行时间
         String taskId = historicActivityInstance.getTaskId(); //获取任务ID
         String processDefinitionId = historicActivityInstance.getProcessDefinitionId(); //获取流程引擎默认ID
         System.out.println(activityId+ "--" +activityName+ "--" +activityType+ "--" +assignee+ "--" +endTime+ "--" +taskId+ "--" +processDefinitionId);
     }
}

26214000_MAJ4.png

说明:

1.通常查询历史流程活动都需要指定一个过滤条件,指定processInstanceId查看具体某一次流程执行过程中所经历的步奏

  • 2.查询历史任务数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 查询历史任务数据
  */
@Test
public void demo12(){
     HistoricTaskInstanceQuery query = processEngine.getHistoryService().createHistoricTaskInstanceQuery();
     List<HistoricTaskInstance> list = query.list();
     for (HistoricTaskInstance historicTaskInstance : list) {
         String id = historicTaskInstance.getId();
         String assignee = historicTaskInstance.getAssignee();
         String executionId = historicTaskInstance.getExecutionId();
         String name = historicTaskInstance.getName();
         String processDefinitionId = historicTaskInstance.getProcessDefinitionId();
         Date endTime = historicTaskInstance.getEndTime();
         System.out.println(id+ "--" +assignee+ "--" +executionId+ "--" +name+ "--" +processDefinitionId+ "--" +endTime);
     }
}

26214001_9rZ7.png

  • 3.查询历史流程实例数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 查询历史流程实例数据
  */
@Test
public void demo13(){
     HistoricProcessInstanceQuery query = processEngine.getHistoryService().createHistoricProcessInstanceQuery();
     List<HistoricProcessInstance> list = query.list();
     for (HistoricProcessInstance historicProcessInstance : list) {
         String id = historicProcessInstance.getId();
         String processDefinitionId = historicProcessInstance.getProcessDefinitionId();
         String startActivityId = historicProcessInstance.getStartActivityId();
         Date startTime = historicProcessInstance.getStartTime();
         System.out.println(id+ "--" +processDefinitionId+ "--" +startActivityId+ "--" +startTime);
     }
}

26213959_JbfH.png

说明:

1.通常查询历史流程实例都需要指定一个过滤条件,指定processDefinitionId查看具体某一次部署所开启的流程或者指定processDefinitionKey查看某个规则下不限版本的所有流程

2.可以选择性添加finished方法控制是否查询未完成的流程实例。在流程开启时,activiti同时在act_ru_execution表和act_hi_procinst表中创建了一条记录,在流程完成之前act_hi_procinst表中实例的结束时间为空

流程变量

流程变量在整个工作流中扮演很重要的作用。例如:请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是流程实例。也就是说各个流程实例的流程变量是不相互影响的。

26214001_tJEE.jpg

  • 设置流程变量

方式一:在启动流程引擎时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 方式一:启动流程引擎时设置流程变量
  */
@Test
public void demo14(){
     Map<String, Object> mapParme = new HashMap<>();
     mapParme.put( "理由一" , "身体不适,需要请假,求批准!" );
     mapParme.put( "理由二" , "我愿意" );
     ProcessInstance instance = processEngine.getRuntimeService().startProcessInstanceByKey( "qjlc" ,mapParme);
     String id = instance.getId();
     String processInstanceId = instance.getProcessInstanceId();
     System.out.println(id+ "--" +processInstanceId);
}

26214000_HAht.png26214002_6isH.png

说明:

1) 在启动流程实例时,通过重载startProcessInstanceByKey的方法可以加载流程变量。

2) 第二个参数要求是Map<String ,Object>类型,意味着可以添加多个流程变量。

                           3)当这段代码执行完以后,会在数据库表act_ru_variable中添加两行记录。

方式二:办理任务时设置

1
2
3
4
5
6
7
8
9
10
11
12
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 方式二:办理任务时设置流程变量
  */
@Test
public void demo15(){
     Map<String, Object> mapParme = new HashMap<>();
     mapParme.put( "理由三" , "3" );
     mapParme.put( "理由四" , "4" );
     processEngine.getTaskService().complete( "1306" , mapParme);
}

26214003_XEI2.png

说明:

1) 利用setVariables方法在任务办理过程中添加一批流程变量。

2) 利用setVariable方法在任务办理过程中添加一个流程变量。

3) TaskService有一个重载 complete方法

方式三:使用RuntimeService的set方法设置

1
2
3
4
5
6
7
8
9
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 方式三:使用RuntimeService的set方法设置
  */
@Test
public void demo16(){
     processEngine.getRuntimeService().setVariable( "1301" , "理由五" , "5" );
}

26214002_n2Y5.png
方式四:使用TaskService的set方法设置

1
2
3
4
5
6
7
8
9
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 方式四:使用TaskService的set方法设置
  */
@Test
public void demo17(){
     processEngine.getTaskService().setVariable( "1404" , "理由6" , "6" );
}

26214003_dXXi.png

自定义的类型,需要实现序列号接口,框架将序列化后的对象存储在act_ge_bytearray表中 

获取流程变量

方式一:使用RuntimeService获取流程变量

1
2
3
4
5
6
7
8
9
10
//获取默认的引擎,默认加载配置文件
     ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
     /**
      * 方式一:使用RuntimeService的get方法获取
      */
     @Test
     public void demo18(){
         Map<String, Object> variables = processEngine.getRuntimeService().getVariables( "1301" );
         System.out.println(variables);
     }

26214003_Mw2x.png

方式二:使用TaskService的get方法获取

1
2
3
4
5
6
7
8
9
10
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 方式二:使用TaskService的get方法获取
  */
@Test
public void demo19(){
     Map<String, Object> variables = processEngine.getTaskService().getVariables( "1404" );
     System.out.println(variables);
}

26214005_RBaP.png

方式三:使用框架提供的表达式获取

26214004_OVaq.jpg

候选组任务

26214004_j1pR.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//获取默认的引擎,默认加载配置文件
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**
  * 创建组,创建用户,用户关联组
  */
@Test
public void demo20(){
     //创建组
     Group group = new GroupEntity();
     group.setId( "发货人员组" );
     processEngine.getIdentityService().saveGroup(group);
     //创建用户
     User user = new UserEntity();
     user.setId( "MD5userID" );
     processEngine.getIdentityService().saveUser(user);
     //用户关联组
     processEngine.getIdentityService().createMembership( "MD5userID" , "发货人员组" );
}

>查询组任务>认领任务

监听器

在流程中我们有时会对整个流程或者一个节点的某种状态做出相应的处理。这时就会用到监听器。Activiti中流程的监听主要分为两大类,执行监听器和任务监听器。

  • 1.执行监听器

1
2
3
4
5
6
7
8
9
10
11
12
package com.mickeymouse.listener;
 
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
 
public class Listener3 implements ExecutionListener{
 
     @Override
     public void notify(DelegateExecution execution) throws Exception {
         System.out.println( "我是执行监听器,这里可以执行需要的操作!" );
     }
}

26214006_7tMz.png

  • 2.任务监听器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.mickeymouse.listener;
 
import java.util.Date;
 
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
 
public class Listener2 implements TaskListener{
 
     @Override
     public void notify(DelegateTask delegateTask) {
         System.out.println( "监听结束... ..." );
         String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
         String assignee = delegateTask.getAssignee();
         Date createTime = delegateTask.getCreateTime();
         String eventName = delegateTask.getEventName();
         String processInstanceId = delegateTask.getProcessInstanceId();
         System.out.println(taskDefinitionKey+ "--" +assignee+ "--" +createTime+ "--" +eventName+ "--" +processInstanceId);
     }
 
}

26214007_0cZK.png

Spring整合activiti

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
     
     <!-- dbcp连接池(导dbcp两个包,一个dbcp驱动包,一个依赖pool包) -->
     < bean id = "basicDataSource" class = "org.apache.commons.dbcp.BasicDataSource" >
         < property name = "driverClassName" value = "com.mysql.jdbc.Driver" ></ property >
         < property name = "url" value = "jdbc:mysql://localhost:3306/activiti" ></ property >
         < property name = "username" value = "root" ></ property >
         < property name = "password" value = "123" ></ property >
     </ bean >
     <!-- 开始事务 -->
     < bean name = "transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" >
         < property name = "dataSource" ref = "basicDataSource" ></ property >
     </ bean >
     <!-- 注册一个流程控制引擎的配置文件对象 -->
     < bean id = "processEngineConfiguration" class = "org.activiti.spring.SpringProcessEngineConfiguration" >
         < property name = "dataSource" ref = "basicDataSource" ></ property >
         < property name = "transactionManager" ref = "transactionManager" ></ property >
         < property name = "databaseSchemaUpdate" value = "true" ></ property >
     </ bean >
     
     
     <!-- 创建流程控制引擎.传入流程控制引擎的配置对象 -->
     < bean id = "processEngine" class = "org.activiti.spring.ProcessEngineFactoryBean" >
         < property name = "processEngineConfiguration" ref = "processEngineConfiguration" ></ property >
     </ bean >
     
     
     < bean name = "repositoryService" factory-bean = "processEngine" factory-method = "getRepositoryService" ></ bean >
     < bean name = "runtimeService" factory-bean = "processEngine" factory-method = "getRuntimeService" ></ bean >
     < bean name = "taskService" factory-bean = "processEngine" factory-method = "getTaskService" ></ bean >
     < bean name = "historyService" factory-bean = "processEngine" factory-method = "getHistoryService" ></ bean >
     < bean name = "identityService" factory-bean = "processEngine" factory-method = "getIdentityService" ></ bean >
     < bean name = "managementService" factory-bean = "processEngine" factory-method = "getManagementService" ></ bean >
</ beans >

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.mickeymouse.test;
 
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class Spring_activiti {
     @Test
     public void test(){
         //加载配置文件
         ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "com/mickeymouse/test/applicationContext.xml" );
         //获取bean对象
         RepositoryService repositoryService = (RepositoryService) applicationContext.getBean( "repositoryService" );
         //部署一个流程引擎(增加一个流程引擎)
         DeploymentBuilder createDeployment = repositoryService.createDeployment();
         createDeployment.addClasspathResource( "activiti.bpmn" );
         createDeployment.addClasspathResource( "activiti.png" );
         Deployment deploy = createDeployment.deploy();
         //打印流程引擎部署ID
         System.out.println(deploy.getId());
     }
}

26214007_wVBk.png

26214008_UuYi.png




转载于:https://my.oschina.net/mickeymouse/blog/522328

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值