必威体育Betway必威体育官网
当前位置:首页 > IT技术

Activiti工作流

时间:2019-09-26 23:42:13来源:IT技术作者:seo实验室小编阅读:83次「手机版」
 

java工作流

Activiti工作

一、Activiti介绍

1、Activiti 的概述

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

​ 工作流管理系统(Workflow Management System, WfMS)是一个软件系统,它完成工作量的定义和管理,并按照在系统中预先定义好的工作流规则进行工作流实例的执行。工作流管理系统不是企业业务系统,而是为企业的业务系统的运行提供了一个软件的支撑环境。

​ 工作流管理联盟(WfMC,Workflow Management Coalition)给出的关于工作流管理系统的定义是:工作流管理系统是一个软件系统,它通过执行经过计算的流程定义去支持一批专门设定的业务流程。工作流管理系统被用来定义、管理、和执行工作流程。

​ 工作流管理系统的目标:管理工作的流程以确保工作在正确的时间被期望的人员所执行——在自动化进行的业务过程中插入人工的执行和干预。

2、常见的开源工作流引擎框架

1、OSWorkFlow

2、JBPM(Jboss business process management)

3、Activiti工作流(是JBPM的升级)

3、Activiti工作流介绍

1、工作流引擎:ProcessEngine对象,它是Activiti的核心类,由该类可以获取其他服务实例(历史服务、创库服务、任务服务、用户参与者服务);

2、BPMN:业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram);

3、数据库(先学后看)

Activiti的后台是有数据库来支持的,所有的表都是由ACT开头的。第二部分是表示表的用途的两个字母标识。

用途也和服务的API对应。Activiti工作流的数据库有23张表。

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

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

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

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

ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件

3.3.1:资源库流程规则表
1)	act_re_deployment 	部署信息表
2)	act_re_model  		流程设计模型部署表
3)	act_re_procdef  		流程定义数据表
3.3.2:运行时数据库表
1)	act_ru_execution		运行时流程执行实例表
2)	act_ru_identitylink		运行时流程人员表,主要存储任务节点与参与者的相关信息
3)	act_ru_task			运行时任务节点表
4)	act_ru_variable		运行时流程变量数据表
3.3.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			历史变量表
3.3.4:组织机构表
1)	act_id_group		用户组信息表
2)	act_id_info			用户扩展信息表
3)	act_id_membership	用户与用户组对应信息表
4)	act_id_user			用户信息表
这四张表很常见,基本的组织机构管理,关于用户认证方面建议还是自己开发一套,组件自带的功能太简单,使用中有很多需求难以满足 
3.3.5:通用数据表
1)	act_ge_bytearray		二进制数据表
2)	act_ge_property			属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录,

二、activiti.cfg.xml(activiti的配置文件)

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

定义数据库配置参数:

jdbcUrl: 数据库的JDBC URL。
jdbcDriver: 对应不同数据库类型的驱动。
jdbcUsername: 连接数据库的用户名。
jdbcPassword: 连接数据库的密码。
基于JDBC参数配置的数据库连接 会使用默认的MyBATis连接池。 下面的参数可以用来配置连接池(来自MyBatis参数):
jdbcMaxActiveConnections: 连接池中处于被使用状态的连接的最大值。默认为10。
jdbcMaxIdleConnections: 连接池中处于空闲状态的连接的最大值。
jdbcMaxCheckoutTime: 连接被取出使用的最长时间,超过时间会被强制回收。 默认为20000(20秒)。
jdbcMaxWaitTime: 这是一个底层配置,让连接池可以在长时间无法获得连接时, 打印一条日志,并重新尝试获取一个连接。(避免因为错误配置导致沉默的操作失败)。 默认为20000(20秒)。
示例数据库配置:

三、activiti开发环境搭建

1:activiti5 软件环境

  1. JDK1.6或者更高版本

  2. 支持的数据库有:h2, mysql, oracle, postgres, mssql, db2等。

  3. 支持activiti5运行的jar包

  4. 开发环境为Eclipse3.7或者以上版本,myeclipse为8.6版本

2:相关资源下载

  1. JDK可以到sun的官网下载

http://www.oracle.com/technetwork/java/javase/downloads/index.html

2)数据库,例如:mysql可以在官网上下载。

http://www.mysql.com

  1. activiti也可以到Activiti官方网站下载得到。

http://activiti.org/download.html

  1. Eclipse3.7或者MyEclipse8.6也可以到相应的网站上获得下载。

3:安装流程设计器(eclipse插件)

3.1:安装方式一

网络的情况下,安装流程设计器步骤如下:

  1. 打开 Help -> Install from site .

在这里插入图片描述

  1. 在如下Install界面板中,点击Add按钮:

1544633977188

  1. 然后填入下列字段:

Name: Activiti BPMN 2.0 designer

Location: http://www.activiti.org/designer/update/

1544634008522

4)回到Install界面,在面板正中列表中把所有展示出来的项目都勾上:

1544634031004

5)点击复选框

在Detail部分记得选中 “Contact all updates sites…” , 因为它会检查所有当前安装所需要的插件并可以被Eclipse下载.

6)安装完以后,点击新建工程new->Other…打开面板

1544634051279

说明安装成功!

3.2:安装方式一

没有网络的情况下,安装流程设计器步骤如下:

1)将activiti-eclipse-plugin.zip的内容放入eclipse根目录的dropins文件夹下;

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

1544634098293

3.3、对流程设计器的使用说明

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

1544634136918

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

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

四、Activiti项目

1、LeaveBill.png

1544680283375

2、LeaveBill.bpmn

LeaveBill.bpmn是上面LeaveBill.png工作流的配置文件

<?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:xsd="http://www.w3.org/2001/XMLSchema" 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="leaveBill" name="leaveProcess" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
      <!--开启了三个工作流-->
    <userTask id="usertask1" name="请假申请" activiti:assignee="张三"></userTask>
    <userTask id="usertask2" name="审批[主管]" activiti:assignee="李四"></userTask>
    <userTask id="usertask3" name="审批[经理]" activiti:assignee="王五"></userTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
    <sequenceFlow id="leaveBill" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_leaveBill">
    <bpmndi:BPMNPlane bpmnElement="leaveBill" id="BPMNPlane_leaveBill">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="295.0" y="20.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="260.0" y="80.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="260.0" y="160.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="260.0" y="250.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="290.0" y="350.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="312.0" y="55.0"></omgdi:waypoint>
        <omgdi:waypoint x="312.0" y="80.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="312.0" y="135.0"></omgdi:waypoint>
        <omgdi:waypoint x="312.0" y="160.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="312.0" y="215.0"></omgdi:waypoint>
        <omgdi:waypoint x="312.0" y="250.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="leaveBill" id="BPMNEdge_leaveBill">
        <omgdi:waypoint x="312.0" y="305.0"></omgdi:waypoint>
        <omgdi:waypoint x="307.0" y="350.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

3、代码方式创建ProcessEngine对象

1、创建工作流引擎及工作流的数据表;

----数据库及表可以自动创建,可以在配置数据库连接时,实现自动创建数据库与表

—获取ProcessEngine对象

​ 的先获取ProcessEngineconfiguration对象,再由该对象来构造ProcessEngine对象

package cn.lice.activiti.a;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.junit.Test;

/**
 * 模拟Activiti工作流
 * 
 * @author 11606
 *
 */
public class TestActiviti {
	// 1.获取的流引擎,自动创建Activiti涉及的表
	@Test
	public void createprocessEngine() {
		// 获取ProcessEngineConfiguration对象,它是抽象 类,不能new出来
		ProcessEngineConfiguration engineConfiguration = ProcessEngineConfiguration
				.createstandaloneProcessEngineConfiguration();
		// 配置数据库连接
		engineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
		engineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/ActivitiDB?createDatabaseIfNotExist=true"
				+ "&useunicode=true&characterEncoding=UTF8");
		engineConfiguration.setJdbcUsername("root");
		engineConfiguration.setJdbcPassword("root");
		// 设置表的创建表的策略(当没有表时,自动创建)
		/**
		 * 
		 * public static final java.lang.String DB_SCHEMA_UPDATE_FALSE = "false"; 不会自动创建表,没有则会抛异常
		 * public static final java.lang.String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop"; 先删除,再创建
		 * public static final java.lang.String DB_SCHEMA_UPDATE_TRUE = "true"; 假如没有则自动创建
		 * 
		 */
		engineConfiguration.setDatabaseSchemaUpdate("true");
		//通过ProcessEngineConfiguration对象,创建ProcessEngine
		ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
		System.out.println("创建ProcessEngine成功:"+processEngine);

	}
}

4、xml方式创建ProcessEngine对象

通过加载activiti.cfg.xml 获取流程引擎和自动创建数据库表

<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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


    <!-- 配置ProcessEngineConfiguration -->
    <bean id="processEngineConfiguration" class=" org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ActivitiDB1?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=UTF8"/>
        <property name="jdbcUsername" value="root"/>
        <property name="jdbcPassword" value="root"/>
        <!-- 创建表策略 -->
        <property name="databaseSchemaUpdate" value="true"></property>
        
    </bean>
</beans>

java代码加载activiti.cfg.xml

//2.xml方式获取的流引擎,自动创建Activiti涉及的表
	@Test
	public void createProcessEngineByXml() {
		ProcessEngineConfiguration engineConfiguration = 
				ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
		ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
		System.out.println("创建ProcessEngine通过xml:"+processEngine);
	}

5、部署流程定义

通过上面的LeaveBill.png与LeaveBill.bpmn已经设计好了工作流程,因此需要将设计好的工作流程部署到系统中

@Test
public void deploy() {
		//获取工作流引擎
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		//获取创库服务:管理流程定义
		RepositoryService pRepositoryService = processEngine.getRepositoryService();
		Deployment deploy = pRepositoryService.createDeployment() //创建一个部署构建器
		.addClasspathResource("diagrams/LeaveBill.bpmn")   //从类路径中添加资源,一次只能添加一个资源
		.addClasspathResource("diagrams/LeaveBill.png")
		.name("请求单流程")  //设置部署名称
		.category("办公类别") //设置部署类别
		.deploy();
		System.out.println("部署的Id:"+deploy.getId());
		System.out.println("部署的name:"+deploy.getName());
		
}

影响的表:

SELECT * FROM `act_re_procdef`;  ---- 流程定义表
SELECT * FROM `act_re_deployment`; ---- 部署表 
SELECT * FROM `act_ge_property`;  --- 通用属性表 id生成策略 next.dbid 影响部署的id

act_re_procdef:流程定义表

1544690357612

该表的key值是bpmn的id决定;该表的name值是bpmn的name属性决定。

act_re_deployment:部署表:id由act_ge_property的next.dbid 决定

1544690635083

act_ge_property:通用属性表

1544690689148

6、启动流程

任务流程部署完成,则需要启动流程

//启动流程
	@Test
	public void startProcess() {
		String processDefikey="leaveBill";
		//取运行的服务
		RuntimeService runtimeService = processEngine.getRuntimeService();
		//通过流程定义的key,来启动流程
		ProcessInstance pInstance = runtimeService.startProcessInstanceByKey(processDefikey);
		System.out.println("流程实例的id:"+pInstance.getId());
		System.out.println("流程定义的id:"+pInstance.getProcessDefinitionId());
		
		
	}

7、任务完成

//完成任务
	@Test
	public void compileTask() {
		String tackId = "204";
		processEngine.getTaskService().complete(tackId);
		System.out.println("当前任务执行完毕");
	}

任务完成

五、管理流程定义

1、涉及的对象及表

涉及的对象:ProcessEngine、RepositoryService、Deployment、ProcessDefinition

涉及的表:

  act_re_deployment:部署对象表
  act_re_procdef:流程定义表
  act_ge_bytearray:资源文件表
  act_ge_property:主键生成策略表

2、设置流程定义图

2.1、流程图设计

1544704952121

2.2、bpmn与png文件

1544704968125

3、部署流程定义

3.1 、通过bpmn与png格式加载及部署

package cn.lice.activiti.b;
//流程定义管理

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;

public class ProcessDefinitionManager {
	private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
	//定义部署
	@Test
	public void deploy() {
		Deployment deployment = processEngine.getRepositoryService()
				.createDeployment()
				.name("采购流程")
				.addClasspathResource("diagrams/BuyBill.bpmn")
				.addClasspathResource("diagrams/BuyBill.png")
				.deploy();
		System.out.println("部署名称:"+deployment.getName());
		System.out.println("部署Id:"+deployment.getId());
	}

}

3.2、通过zip格式加载及部署

//定义部署,zip格式
	@Test
	public void deployByZip() {
		//从类路径中获取文件getClass().getClassLoader().getResourceAsStream("BuyBill.zip")
		InputStream in = getClass().getClassLoader().getResourceAsStream("BuyBill.zip");
		Deployment deployment = processEngine.getRepositoryService()
				.createDeployment()
				.name("采购流程")
				.addZipInputStream(new ZipInputStream(in))
				.deploy();
		System.out.println("部署名称:"+deployment.getName());
		System.out.println("部署Id:"+deployment.getId());
	}

3.3、查看流定义

//查看流程定义
	@Test
	public void queryProcessDefinition() {
		String proDefiKey = "BuyBill";
		List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
				//查询,相当于where
//				.processDefinitionCategory(category) // 流程定义目录
//				.processDefinitionId(id)  //流程定义id
//				.processDefinitionKey(proDefiKey)  //流程定义key
//				.processDefinitionName(name)   //流程定义name
//				.processDefinitionVersion(version) //流程定义版本
//				.latestVersion()  //最新版本
				.orderbyProcessDefinitionVersion().desc()  //排序 按版本降序
				
				//结果
//				.count()  //统计数
//				.listPage(arg0, arg1)  //分页
				.list();
		if (list!=null&& list.size()>0) {
			for (ProcessDefinition processDefinition : list) {
				System.out.print("流程定义id:"+processDefinition.getId());
				System.out.print("流程定义name:"+processDefinition.getName());
				System.out.print("流程定义版本:"+processDefinition.getVersion());
				System.out.print("流程定义部署id:"+processDefinition.getDeploymentId());
				System.out.println("流程定义key:"+processDefinition.getKey());				
			}
		}
				
				
	}

3.4、删除流定义

通过创库服务,根据部署id来删除流程定义。删除之后,与它相关的表都会被删除!

//删除流程定义
	@Test
	public void deleteProcessDefi() {
		//获取工作流引擎,以及创库服务,通过流程部署id来删除
		String deployId = "1";
		processEngine.getRepositoryService().deleteDeployment(deployId);
	}

3.5 、获取流定义的文档的资源(查看流程图附加)

3.6、查看最新版本的流定义

processEngine.getRepositoryService().createProcessDefinitionQuery().latestVersion()  //最新版本

六、流程实例、任务执行

1、涉及的对象及表

2、启动流程实例

private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
	
	//流程定义开始
	@Test
	public void startProcess() {
		String processDefiKey = "buyBill";
		ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefiKey);
		System.out.println("流程执行对象的id:"+processInstance.getId());
		System.out.println("流程实例对象的id:"+processInstance.getProcessInstanceId());
		System.out.println("流程定义的id:"+processInstance.getProcessDefinitionId());
	}

3、查看的我的任务

//查询正在运行的任务,所有的正在执行的任务
	@Test
	public void queryTask() {
		TaskService taskService = processEngine.getTaskService();
		//创建一个任务对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		//办理人任务列表
		List<Task> list = (List<Task>) taskQuery.list();
		//遍历办理人
		if (list!=null && list.size()>0) {
			for (Task task : list) {
				System.out.println("任务办理人:"+task.getAssignee());
				System.out.println("任务id:"+task.getId());
				System.out.println("任务name:"+task.getName());
			}
		}		
	}

4、办理任务(完成任务)

//完成任务
	@Test
	public void compileTask() {
		String tackId = "604";
		processEngine.getTaskService().complete(tackId);
		System.out.println("当前任务执行完毕");
	}

5、查询流程实例状态(判断流程正在执行,还是结束)

//获取流程实例的状态
	@Test
	public void queryProcessTaskState() {
		String processInstanceId="201";
		ProcessInstance pInstance = processEngine.getRuntimeService().createProcessInstanceQuery()
		.processInstanceId(processInstanceId)
		.singleResult();//返回的数据要么是单例,要么是空
		//判断流程实例的状态
		if (pInstance!=null) {
			System.out.println("该流程实例:"+processInstanceId+"在运行....."+pInstance.getActivityId());
		}else {
			System.out.println("当前的流程实例"+pInstance+"已经结束");
		}
	}

SELECT * FROM `act_hi_procinst`;  --- 历史流程实例表

6、查看历史任务

SELECT * FROM `act_hi_taskinst`;  --- 历史流程任务表
//查历史流程的实例的信息
	@Test
	public void queryHistoryProcessInstance() {
		List<HistoricProcessInstance> list = 
				(List<HistoricProcessInstance>) processEngine.getHistoryService()
				.createHistoricProcessInstanceQuery()
				.list();
		if (list!=null && list.size()>0) {
			for (HistoricProcessInstance historicProcessInstance : list) {
				System.out.println("历史流程实例id:"+historicProcessInstance.getId());
				System.out.println("历史流程实例定义的id:"+historicProcessInstance.getProcessDefinitionId());
			}
		}
	}

7、查看历史流程实例

//查看历史执行流程的任务信息
	@Test
	public void queryHistoryTask() {
		String processInstanceId="601";
		List<HistoricTaskInstance> list = 
				(List<HistoricTaskInstance>) processEngine.getHistoryService()
				.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.list();
		if (list!=null && list.size()>0) {
			for (HistoricTaskInstance historicTaskInstance : list) {
				System.out.println("历史流程实例id:"+historicTaskInstance.getId());
				System.out.println("历史流程定义实例id:"+historicTaskInstance.getProcessDefinitionId());
				System.out.println("历史流程任务的名称:"+historicTaskInstance.getName());
				System.out.println("历史流程任务处理人:"+historicTaskInstance.getAssignee());
			}
		}
	}

七、流程变量

涉及到的表

​ act_ru_variable:正在执行的流程变量表

​ act_hi_varinst:流程变量历史表

1、流程变量的作用

----传递业务参数(申请人、天数、事件、原因)

----动态指定办理人

-----指定连接,完成任务(同意或拒绝)

2、设置简易的bpmn流程图

1544778792210

3、部署流程定义及启动流程实例

ic class ProcessVariable {
	private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

	// 定义部署
	@Test
	public void deploy() {
		Deployment deployment = processEngine.getRepositoryService().createDeployment().name("支付流程")
				.addClasspathResource("diagrams/APPayBill.bpmn").addClasspathResource("diagrams/appayBill.png")
				.deploy();
		System.out.println("部署名称:" + deployment.getName());
		System.out.println("部署Id:" + deployment.getId());
	}

	// 流程定义开始
	@Test
	public void startProcess() {
		String processDefiKey = "appayBill";
		ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefiKey);
		System.out.println("流程执行对象的id:" + processInstance.getId());
		System.out.println("流程实例对象的id:" + processInstance.getProcessInstanceId());
		System.out.println("流程定义的id:" + processInstance.getProcessDefinitionId());
	}
	

4、设置流程变量

  • 通过 TaskService 和 RuntimeService 服务设置变量

  • Execution 与 ProcessInstance 区别

    1. Execution:只一个流程实例具体要执行的过程对象
    2. ProcessInstance:流程实例 ProcessInstance(1)–>Execution(N) ,且N>=1
    3. 值等情况: act_ru_execution 的id和 proc_inst_id 相同 ,该流程没有子流程
    4. 值不等情况: 只会出现在子流程中(嵌套、引入),act_ru_execution 的id和 proc_inst_id 不相同,但parent_id 等于当前流程实例的 id 和proc_inst_id
    5. 比如一个购物流程中除了下单、出库节点,

      可能还有一个付款子流程,一般付款流程都是作为公用的流程,当任务达到子流程时,引擎会自动创建一个付款子流程

  • setValiable 与 setLocalValiable区别 作用域 : page、requestsession、application

    //设置流程变量值
    	@Test
    	public void setVariable(){
    		String taskId="1804";//任务id
    		//采用TaskService来设置流程变量
    		
    		//1. 第一次设置流程变量
    //		TaskService taskService = processEngine.getTaskService();
    //		taskService.setVariable(taskId, "cost", 1000);//设置单一的变量,作用域在整个流程实例
    //		taskService.setVariable(taskId, "申请时间", new Date());
    //		taskService.setVariableLocal(taskId, "申请人", "何某某");//该变量只有在本任务中是有效的
    		
    		
    		//2. 在不同的任务中设置变量
    //		TaskService taskService = processEngine.getTaskService();
    //		taskService.setVariable(taskId, "cost", 5000);//设置单一的变量,作用域在整个流程实例
    //		taskService.setVariable(taskId, "申请时间", new Date());
    //		taskService.setVariableLocal(taskId, "申请人", "李某某");//该变量只有在本任务中是有效的
    		
    		/**
    		 * 3. 变量支持的类型
    		 * - 简单的类型 :String 、boolean、integer、double、date 
    		 * - 自定义对象bean  
    		 */
    		TaskService taskService = processEngine.getTaskService();
    		//传递的一个自定义bean对象
    		AppayBillBean appayBillBean=new AppayBillBean();
    		appayBillBean.setId(1);
    		appayBillBean.setCost(300);
    		appayBillBean.setDate(new Date());
    		appayBillBean.setAppayPerson("何某某");
    		taskService.setVariable(taskId, "appayBillBean", appayBillBean);
    		
    		
    		System.out.println("设置成功!");
    
    	}
    	
    
    import java.util.Date;
    
    public class AppayBillBean {
    	private Integer id;
    	private Integer cost;//金额
    	private String appayPerson;//申请人
    	private Date date;//申请日期
    	public Integer getId() {
    		return id;
    	}
    	public void setId(Integer id) {
    		this.id = id;
    	}
    	public Integer getCost() {
    		return cost;
    	}
    	public void setCost(Integer cost) {
    		this.cost = cost;
    	}
    	public String getAppayPerson() {
    		return appayPerson;
    	}
    	public void setAppayPerson(String appayPerson) {
    		this.appayPerson = appayPerson;
    	}
    	public Date getDate() {
    		return date;
    	}
    	public void setDate(Date date) {
    		this.date = date;
    	}
    	
    }
    
    

5、获取流程变量

//模拟流程变量设置
	@Test
	public void  getAndSetProcessVariable(){
		//有两种服务可以设置流程变量
//		TaskService taskService = processEngine.getTaskService();
//		RuntimeService runtimeService = processEngine.getRuntimeService();
		
		/**1.通过 runtimeService 来设置流程变量
		 * exxcutionId: 执行对象
		 * variableName:变量名
		 * values:变量值
		 */
//		runtimeService.setVariable(exxcutionId, variableName, values);
//		runtimeService.setVariableLocal(executionId, variableName, values);
		//设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
//		runtimeService.setVariables(exxcutionId, variables); 
		  //可以设置多个变量  放在 Map<key,value>  Map<String,Object>
		
		/**2. 通过TaskService来设置流程变量
		 * taskId:任务id
		 */
//		taskService.setVariable(taskId, variableName, values);
//		taskService.setVariableLocal(taskId, variableName, values);
////		设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
//		taskService.setVariables(taskId, variables); //设置的是Map<key,values>
		
		/**3. 当流程开始执行的时候,设置变量参数
		 * processDefiKey: 流程定义的key
		 * variables: 设置多个变量  Map<key,values>
		 */
//		processEngine.getRuntimeService()
//		.startProcessInstanceByKey(processDefiKey, variables)
		
		/**4. 当执行任务时候,可以设置流程变量
		 * taskId:任务id
		 * variables: 设置多个变量  Map<key,values>
		 */
//		processEngine.getTaskService().complete(taskId, variables);
		
		
		/** 5. 通过RuntimeService取变量值
		 * exxcutionId: 执行对象
		 * 
		 */
//		runtimeService.getVariable(exxcutionId, variableName);//取变量
//		runtimeService.getVariableLocal(exxcutionId, variableName);//取本执行对象的某个变量
//		runtimeService.getVariables(variablesName);//取当前执行对象的所有变量
		/** 6. 通过TaskService取变量值
		 * TaskId: 执行对象
		 * 
		 */
//		taskService.getVariable(taskId, variableName);//取变量
//		taskService.getVariableLocal(taskId, variableName);//取本执行对象的某个变量
//		taskService.getVariables(taskId);//取当前执行对象的所有变量
	}

6、查询历史的流程变量

7、流程变量支持的类型

八、连线

连线中,只有一条线程;没有并行的任务。有点像Java中的if流程。

  1. 设置bpmn流程图

  2. 部署和执行流程

  3. 查询和完成任务

  4. 如何设置条件变量

    连线–>main config–>condition

    表达式的结果必须是布尔型

    • #{variable==‘value’}
    • ${variable==value}
  5. 总结

    一个活动中可以指定一个或多个SequenceFlow(Start中有一个,End中没有)。

    • 开始活动中有一个SequenceFlow 。
    • 结束活动中没有SequenceFlow 。
    • 其他活动中有1条或多条SequenceFlow

    如果只有一个,则可以不使用流程变量设置codition的名称;

1544854858285

连线代码:

package cn.lice.activiti.e;

import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.junit.Test;

//连线流程
public class SequenceFlow {
	private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

	// 定义部署
	@Test
	public void deploy() {
		Deployment deployment = processEngine.getRepositoryService().createDeployment().name("连线流程")
				.addClasspathResource("diagrams/SequenceFlow.bpmn")
				.deploy();
		System.out.println("部署名称:" + deployment.getName());
		System.out.println("部署Id:" + deployment.getId());
	}

	// 流程定义开始
	@Test
	public void startProcess() {
		String processDefiKey = "sequenceBill";
		ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey(processDefiKey);
		System.out.println("流程执行对象的id:" + processInstance.getId());
		System.out.println("流程实例对象的id:" + processInstance.getProcessInstanceId());
		System.out.println("流程定义的id:" + processInstance.getProcessDefinitionId());
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery.list();
		// 遍历任务列表
		if (list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任务的办理人:" + task.getAssignee());
				System.out.println("任务的id:" + task.getId());
				System.out.println("任务的名称:" + task.getName());
			}
		}

	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "1502";
		// taskId:任务id
		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}

}

设置信息,让工作流程按照指定的连线去执行

// 完成任务
	@Test
	public void compileTask() {
		String taskId = "1204";
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("message", "不知道重不重要");
		// taskId:任务id
		processEngine.getTaskService().complete(taskId, params);
//		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}

总结:

1、一个活动中可以指定一个或多个SequenceFlow(Start中有一个,End中没有)。

* 开始活动中有一个SequenceFlow 。

* 结束活动中没有SequenceFlow 。

* 其他活动中有1条或多条SequenceFlow

2、如果只有一个,则可以不使用流程变量设置codition的名称;

1544855260968

如果有多个,则需要使用流程变量设置codition的名称。message表示流程变量的名称,‘不重要’表示流程变量的值,${}中间的内容要使用boolean类型的表达式,用来判断应该执行的连线。

1544855228367

九、排他网关(ExclusiveGateWay)

  1. 设置bpmn流程图

  2. 1544856144795

  3. 部署与执行流程

    package cn.lice.activiti.f;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.activiti.engine.ProcessEngine;
    import org.activiti.engine.ProcessEngines;
    import org.activiti.engine.TaskService;
    import org.activiti.engine.repository.Deployment;
    import org.activiti.engine.runtime.ProcessInstance;
    import org.activiti.engine.task.Task;
    import org.activiti.engine.task.TaskQuery;
    import org.junit.Test;
    
    //排他网关
    public class ExclusiveGateway {
    	private ProcessEngine processEngine = ProcessEngines
    			.getDefaultProcessEngine();
    
    	// 部署流程定义,资源来在bpmn格式
    	@Test
    	public void deployProcessDefi() {
    		Deployment deploy = processEngine.getRepositoryService()
    				.createDeployment().name("排他网关流程")
    				.addClasspathResource("diagrams/ExclusiveGateway.bpmn")
    				.deploy();
    
    		System.out.println("部署名称:" + deploy.getName());
    		System.out.println("部署id:" + deploy.getId());
    	}
    
    	// 执行流程,开始跑流程
    	@Test
    	public void startProcess() {
    		String processDefiKey = "bankBill";// bpmn 的 process id属性
    		ProcessInstance pi = processEngine.getRuntimeService()
    				.startProcessInstanceByKey(processDefiKey);
    
    		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
    		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance
    																	// 对象
    		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
    	}
    
    	// 查询正在运行任务
    	@Test
    	public void queryTask() {
    		// 取得任务服务
    		TaskService taskService = processEngine.getTaskService();
    		// 创建一个任务查询对象
    		TaskQuery taskQuery = taskService.createTaskQuery();
    		// 办理人的任务列表
    		List<Task> list = taskQuery.list();
    		// 遍历任务列表
    		if (list != null && list.size() > 0) {
    			for (Task task : list) {
    				System.out.println("任务的办理人:" + task.getAssignee());
    				System.out.println("任务的id:" + task.getId());
    				System.out.println("任务的名称:" + task.getName());
    			}
    		}
    
    	}
    
  4. 查询和完成任务

    
    	// 完成任务
    	@Test
    	public void compileTask() {
    		String taskId = "1501";
    		Map<String,Object> params=new HashMap<String, Object>();
    		params.put("visitor", 6);
    		// taskId:任务id
    		processEngine.getTaskService().complete(taskId, params);
    //		processEngine.getTaskService().complete(taskId);
    		System.out.println("当前任务执行完毕");
    	}
    
  5. 总结

    1.一个排他网关对应一个以上的顺序流

    2.由排他网关流出的顺序流都有个conditionExpression元素,在内部维护返回boolean类型的决策结果。

    3.决策网关只会返回一条结果。当流程执行到排他网关时,流程引擎会自动检索网关出口,从上到下检索如果发现 第一条决策结果为true或者没有设置条件的(默认为成立),则流出。

    4.如果没有任何一个出口符合条件,则抛出异常

    5.使用流程变量,设置连线的条件,并按照连线的条件执行工作流,如果没有条件符合的条件,则以默认的连线离开,但是默认的连线不能设置条件

十、并行网关

1、流程图

![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)

2、部署流程定义+启动流程实例

![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg)

3、查询我的个人任务

![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg)

4、完成我的个人任务

![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg)

说明:

1) 一个流程中流程实例只有1个,执行对象有多个

2) 并行网关的功能是基于进入和外出的顺序流的:

分支(fork): 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。

汇聚(join): 所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关。

3) 并行网关的进入和外出都是使用相同节点标识

4) 如果同一个并行网关有多个进入和多个外出顺序流, 它就同时具有分支和汇聚功能。 这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。

5) 并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略。

6) 并行网关不需要是“平衡的”(比如, 对应并行网关的进入和外出节点数目不一定相等)。如图中标示是合法的:![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image010.gif)

5、开始活动节点

5.1、流程图

![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image011.gif)

5.2 、部署流程定义+启动流程实例+查询流程实例+查询历史流程实例

![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image013.jpg)

6、总结

1):结束节点没有出口

2):其他节点有一个或多个出口。

如果有一个出口,则代表是一个单线流程

如果有多个出口,则代表是开启并发流程

7、接收活动(receiveTask,即等待活动)

接收任务是一个简单任务,它会等待对应消息的到达。 当前,官方只实现了这个任务的java语义。 当流程达到接收任务,流程状态会保存到数据库中。

在任务创建后,意味着流程会进入等待状态, 直到引擎接收了一个特定的消息, 这会触发流程穿过接收任务继续执行。

7.1、流程图

![img](file:///C:/Users/11606/AppData/Local/Temp/msohtmlclip1/01/clip_image017.gif)

7.2、部署流程定义+启动流程实例

/**

     * ReceiceTask任务,机器自动完成的任务

     * 只会在act_ru_execution表中产生一条数据

     * @throws Exception

     */

    

    @Test

    public void testExecution() throws Exception {

        // 1 发布流程

        InputStream inputStreamBpmn = this.getClass().getResourceAsStream("receiveTask.bpmn");

        InputStream inputStreamPng = this.getClass().getResourceAsStream("receiveTask.png");

        processEngine.getRepositoryService()//

                        .createDeployment()//

                        .addInputStream("receiveTask.bpmn", inputStreamBpmn)//

                        .addInputStream("receiveTask.png", inputStreamPng)//

                        .deploy();

        

        // 2 启动流程

        ProcessInstance pi = processEngine.getRuntimeService()//

                            .startProcessInstanceByKey("receiveTaskDemo");

        System.out.println("pid:" + pi.getId());

        String pid = pi.getId();

        

        // 3**查询是否有一个执行对象在描述”汇总当日销售额“**

        Execution e1 = processEngine.getRuntimeService()//

                        .createExecutionQuery()//

                        .processInstanceId(pid)//

                        .activityId("汇总当日销售额")//

                        .singleResult();

 

        // 4**执行一堆逻辑,并设置流程变量**

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

        vars.put("当日销售额", 10000);

        //  5**流程向后执行一步:往后推移e1,使用signal给流程引擎信号,告诉他当前任务已经完成了,可以往后执行**

        processEngine.getRuntimeService()

                .signal(e1.getId(),vars);

        

        // 6**判断当前流程是否在”给老板发短信“节点**

        Execution e2 = processEngine.getRuntimeService()//

                        .createExecutionQuery()//

                        .processInstanceId(pid)//

                        .activityId("给总经理发短信")//

                        .singleResult();

        

        // 7**获取流程变量**

        Integer money = (Integer) processEngine.getRuntimeService()//

                                .getVariable(e2.getId(), "当日销售额");

        System.out.println("老板,今天赚了" +money);

        // 8**向后执行一步:任务完成,往后推移”给老板发短信“任务**

        processEngine.getRuntimeService()//

                .signal(e2.getId());

        

        

        // 9**查询流程状态**

        pi = processEngine.getRuntimeService()//

                     .createProcessInstanceQuery()//

                     .processInstanceId(pid)//

                     .singleResult();

        if(pi==null){

             System.out.println("流程正常执行!!!,已经结束了");

        }

    }

说明:

1) 当前任务(一般指机器自动完成,但需要耗费一定时间的工作)完成后,向后推移流程,可以调用runtimeService.signal(executionId),传递接收执行对象的id。

十一、用户任务(userTask)

  1. 个人任务
    • 个人分配任务方式1:直接指定
    • 个人分配任务方式2:采用流程变量

相关阅读

UCML工作流使用案例

【案例背景:申请者填写申请单,启动流程,如果不大于10万元,部门经理审批,同意则告知申请人,不同意则流程直接结束;如果大于10万元,总经理审

软件开发工作流程

工作流使用

有工作流使用经验的朋友请进来,最近在做一个工作流方面的项目;

图解两个工作流程图怎么制作的技巧

在工作中我们使用流程图的频率极高,一方面利用它能清楚展示各个项目活动的流程,另一方面还可以明确各部分之间的逻辑关系。这么实用

哪种“工作流”更高效?三大协同管理OA系统对比大不同

某家公司接手新项目,需要市场营销部做出推广&rarr;市场部对接好业务&rarr;活动部协调好发布会,在整个过程中,多个部分、多位工作人员

分享到:

栏目导航

推荐阅读

热门阅读