Java进阶学习第三十五天(Activiti工作流)

版权声明:使用本品须Jack Gao同意,违者必究 https://blog.csdn.net/Mr_GaoYang/article/details/85258197

一、工作流概念

1、生活中的工作流:请假流程

2、理解工作流概念
① 定义工作流 : 包括定义具体的活动、规则等
② 执行工作流 : 按照流程定义的规则去执行,并且由多个参与者进行控制

二、Activiti工作流

1、Activiti工作流介绍
① 常见开源工作流引擎框架:OSWorkFlow、JBPM(java business process management)、Activiti工作流(是对JBPM升级)
② 工作流引擎:ProcessEngine ,它是Activiti的核心类,由该类可以获取其他的服务实例(历史服务、仓库服务、任务服务、用户参与者服务)
③ BPMN
业务流程建模与标注(Business Process Model and Notation,BPMN) 描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)
④ 数据库
Activiti的工作流数据库有23张表,Activiti的后台是有数据库的支持,所有的表都以ACT_开头。第二部分是表示表的用途的两个字母标识,用途也和服务的API对应

act_ge_*:通用表
act_hi_*:历史流程相关表 
act_re_*:仓库表:保存流程定义
act_ru_*:保存流程运行相关的表  
act_id_*:用户参与相关的表  

⑤ activiti.cfg.xml
Activiti核心配置文件,配置流程引擎创建工具的基本参数和数据库连接参数
⑥ logging.properties

2、搭建Activiti开发环境
① Acitiviti软件环境
◇ JDK 1.6版本及以上
◇ 数据库支持的有:h2、mysql、oracle、mssql、db2等 ,这里选择mysql
◇ 支持Activiti 5 运行的jar包,在activiti-5.13\wars\activiti-rest \WEB-INF\lib添加,可以在官网下载www.activiti.org
◇ 集成开发环境:Myeclipse 8.6及以上,最好myeclipse 2014
② 安装流程设计器BPMN
◇ 有网络安装
◇ 无网情况:直接添加插件 ,把压缩包中的内容放入eclipse根目录的dropins文件夹下
◇ 注意:打开菜单Windows > Preferences > Activit > Save actions(*.bpmn*.png同步保存)

3、Activiti 架构及核心API

activiti.cfg.xml
ProcessEngineConfigration
ProcessEngine
RepositoryService:流程定义 ,存放资源
TaskService :任务服务
IdentityService :用户与组服务
FormService  :表单服务
RuntimeService :运行时服务
ManagementService :管理服务
HistoryService :历史服务

Activiti-Api关系

三、模拟Activiti流程引擎框架执行

1、设置流程定义图bpmn
assignee:指定谁来处理这个任务

2、创建流程引擎及工作流数据表
① 数据库及表可以自动创建,可以在配置数据库连接时,实现自动创建数据库和表
② 取得ProcessEngine对象(先取得ProcessEngineConfiguration 对象,再由该对象来构建ProcessEngine)

/*
 * 模拟Activiti 工作流框架执行
 */
public class TestActiviti {
	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	//取得流程引擎,且自动创建Activiti涉及的数据库和表
	@Test
	public void createProcessEngine(){
		/**   第一种方式:通过代码形式创建ProcessEngine
		 *  - 取得ProcessEngineConfiguration对象
		 *  - 设置数据库连接属性
		 *  - 设置创建表的策略 (当没有表时,自动创建表)
		 *  - 通过ProcessEngineConfiguration对象创建 ProcessEngine 对象
		//取得ProcessEngineConfiguration对象
		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("1234");
		// 设置创建表的策略 (当没有表时,自动创建表)
//		  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("流程引擎创建成功!");
		*/
		
		/**   第二种方式:通过加载 activiti.cfg.xml 获取流程引擎和自动创建数据库及表
		 * 
		ProcessEngineConfiguration engineConfiguration=
				ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
		//从类加载路径中查找资源  activiti.cfg.xm文件名可以自定义
		ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
		System.out.println("使用配置文件Activiti.cfg.xml获取流程引擎");
		*/
		
		/**   第三种方式:通过ProcessEngines来获取默认的流程引擎
		 * 
		 */
		//默认会加载类路径下的 activiti.cfg.xml 
//		ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
//		System.out.println("通过ProcessEngines来获取流程引擎");
	}
	
	//部署流程定义
	@Test
	public void deploy(){
		//取得流程引擎对象
//		ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
		//获取仓库服务 :管理流程定义
		RepositoryService repositoryService = processEngine.getRepositoryService();
		Deployment deploy = repositoryService.createDeployment()//创建一个部署的构建器
		.addClasspathResource("diagrams/LeaveBill.bpmn")//从类路径中添加资源,一次只能添加一个资源
		.addClasspathResource("diagrams/LeaveBill.png")//从类路径中添加资源,一次只能添加一个资源
		.name("请求单流程")//设置部署的名称
		.category("办公类别")//设置部署的类别
		.deploy();
		System.out.println("部署的id"+deploy.getId());
		System.out.println("部署的名称"+deploy.getName());
	}
	
	//执行流程
	@Test
	public void startProcess(){
		String processDefiKey="leaveBill";
		//取运行时服务
		RuntimeService runtimeService = processEngine.getRuntimeService();
		//取得流程实例
		ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefiKey);//通过流程定义的key来执行流程
		System.out.println("流程实例id:"+pi.getId());//流程实例id
		System.out.println("流程定义id:"+pi.getProcessDefinitionId());//输出流程定义的id
	}
	
	//查询任务 
	@Test
	public void queryTask(){
		//任务的办理人
		String assignee="王五";
		//取得任务服务
		TaskService taskService = processEngine.getTaskService();
		//创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		//办理人的任务列表
		List<Task> list = taskQuery.taskAssignee(assignee)//指定办理人
		.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="402";
		//taskId:任务id
		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
}

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.StandaloneProcessEngineConfiguration">
  <!-- 配置数据库连接 -->
  <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
  <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activitiDB?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf8"></property>
  <property name="jdbcUsername" value="root"></property>
  <property name="jdbcPassword" value="1234"></property>
  <!-- 配置创建表策略 :没有表时,自动创建 -->
  <property name="databaseSchemaUpdate" value="true"></property>
 </bean>
</beans>

3、部署流程
影响的表:
act_re_procdef (流程定义表):该表的key属性是由bpmn的id决定, 该表的name属性是由bpmn的name属性决定
act_re_deployment(部署表):id是由act_ge_property的 next_dbid决定
act_ge_property( 通用属性表)
4、执行流程
5、查询任务
6、完成任务

四、管理流程定义

1、涉及的对象及表
① 对象: ProcessEngine 、RepositoryService、Deployment 、ProcessDefinition
② 表:

act_re_deployment:部署对象表
act_re_procdef:流程定义表
act_ge_bytearray: 字节资源表
act_ge_property:主键生成策略表,next_dbId会作为部署表的id

2、设置流程定义图
① 流程图设计
② bpmn与png文件

3、部署流程定义
① 通过bpmn和png格式加载及部署
② 通过Zip格式加载及部署
③ 查看流程定义
④ 删除流程定义
⑤ 获取流程定义文档的资源(查看流程图附加)
⑥ 查看最新版本的流程定义

//流程定义管理
public class ProcessDefinitionManager {
	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	//部署流程定义1:资源来在bpmn格式
	@Test
	public void deployProcessDefi(){
		Deployment deploy = processEngine.getRepositoryService()
		.createDeployment()
		.name("采购流程")
		.addClasspathResource("diagrams/BuyBill.bpmn")
		.addClasspathResource("diagrams/BuyBill.png")
		.deploy();
		System.out.println("部署名称:"+deploy.getName());
		System.out.println("部署id:"+deploy.getId());
	}
	
	//部署流程定义2:资源来自zip格式
	@Test
	public void deployProcessDefiByZip(){
		InputStream in=getClass().getClassLoader().getResourceAsStream("BuyBill.zip");
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment()
				.name("采购流程")
				.addZipInputStream(new ZipInputStream(in))
				.deploy();
		System.out.println("部署名称:"+deploy.getName());
		System.out.println("部署id:"+deploy.getId());
	}
	
	//查看流程定义
	@Test
	public void queryProcessDefination(){
		String processDefiKey="buyBill";//流程定义key
		//获取流程定义列表
		List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
		//查询 ,好比where
//		.processDefinitionId(proDefiId) //流程定义id
		 // 流程定义id  : buyBill:2:704   组成 : proDefikey(流程定义key)+version(版本)+自动生成id
		.processDefinitionKey(processDefiKey)//流程定义key 由bpmn 的 process 的  id属性决定
//		.processDefinitionName(name)//流程定义名称  由bpmn 的 process 的  name属性决定
//		.processDefinitionVersion(version)//流程定义的版本
		.latestVersion()//最新版本
		//排序
		.orderByProcessDefinitionVersion().desc()//按版本的降序排序
		//结果
//		.count()//统计结果
//		.listPage(arg0, arg1)//分页查询
		.list();
		//遍历结果
		if(list!=null&&list.size()>0){
			for(ProcessDefinition temp:list){
				System.out.print("流程定义的id: "+temp.getId());
				System.out.print("流程定义的key: "+temp.getKey());
				System.out.print("流程定义的版本: "+temp.getVersion());
				System.out.print("流程定义部署的id: "+temp.getDeploymentId());
				System.out.println("流程定义的名称: "+temp.getName());
			}
		}
	}
	
	//查看bpmn 资源图片
	@Test
	public void viewImage() throws Exception{
		String deploymentId="601";
		String imageName=null;
		//取得某个部署的资源的名称  deploymentId
		List<String> resourceNames = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);
		// buybill.bpmn  buybill.png 
		if(resourceNames!=null&&resourceNames.size()>0){
			for(String temp :resourceNames){
				if(temp.indexOf(".png")>0){
					imageName=temp;
				}
			}
		}
		
		/**
		 * 读取资源
		 * deploymentId:部署的id
		 * resourceName:资源的文件名
		 */
		InputStream resourceAsStream = processEngine.getRepositoryService()
				.getResourceAsStream(deploymentId, imageName);
		//把文件输入流写入到文件中
		File file=new File("d:/"+imageName);
		FileUtils.copyInputStreamToFile(resourceAsStream, file);
	}
	
	//删除流程定义
	@Test
	public void deleteProcessDefi(){
		//通过部署id来删除流程定义
		String deploymentId="101";
		processEngine.getRepositoryService().deleteDeployment(deploymentId);
	}
}

五、流程实例和流程任务

1、涉及的对象及表
① Execution:执行对象,按流程定义的规则执行一次的过程
对应的表:

act_ru_execution: 正在执行的信息
act_hi_procinst:已经执行完的历史流程实例信息
act_hi_actinst:存放历史所有完成的活动

② ProcessInstance:流程实例,特指流程从开始到结束的那个最大的执行分支,一个执行的流程中流程实例只有1个。
注意
◇ 如果是单例流程,执行对象ID就是流程实例ID
◇ 如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同
◇ 一个流程中,流程实例只有1个,执行对象可以存在多个。
③ Task:任务
执行到某任务环节时生成的任务信息。
对应的表:

act_ru_task:正在执行的任务信息
act_hi_taskinst:已经执行完的历史任务信息

2、启动流程实例
3、查看我的个人任务
4、办理任务(完成任务)
5、查询流程实例状态(判断流程是正在执行还是结束)
6、查询历史任务
7、查看历史流程实例

public class ProcessInstanceAndTask {
	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	//部署流程定义  ,采用buyBill
	//执行流程,开始跑流程
	@Test
	public void startProcess(){
		String processDefiKey="buyBill";//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());
			}
		}
	}
	
	//完成任务
	@Test
	public void compileTask(){
		String taskId="1002";
		//taskId:任务id
		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
	
	//获取流程实例的状态
	@Test
	public void getProcessInstanceState(){
		String processInstanceId="801";
		 ProcessInstance pi = processEngine.getRuntimeService()
		 .createProcessInstanceQuery()
		 .processInstanceId(processInstanceId)
		 .singleResult();//返回的数据要么是单行,要么是空 ,其他情况报错
		 //判断流程实例的状态
		 if(pi!=null){
			 System.out.println("该流程实例"+processInstanceId+"正在运行...  "+"当前活动的任务:"+pi.getActivityId());
		 }else{
			 System.out.println("当前的流程实例"+processInstanceId+" 已经结束!");
		 } 
	}
	
	//查看历史执行流程实例信息
	@Test
	public void queryHistoryProcInst(){
		List<HistoricProcessInstance> list = processEngine.getHistoryService()
		.createHistoricProcessInstanceQuery()
		.list();
		if(list!=null&&list.size()>0){
			for(HistoricProcessInstance temp:list){
				System.out.println("历史流程实例id:"+temp.getId());
				System.out.println("历史流程定义的id:"+temp.getProcessDefinitionId());
				System.out.println("历史流程实例开始时间--结束时间:"+temp.getStartTime()+"-->"+temp.getEndTime());
			}
		}
	}
	
	//查看历史执行流程任务信息
	@Test
	public void queryHistoryTask(){
		String processInstanceId="801";
		List<HistoricTaskInstance> list = processEngine.getHistoryService()
				.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.list();
		if(list!=null&&list.size()>0){
			for(HistoricTaskInstance temp:list){
				System.out.print("历史流程实例任务id:"+temp.getId());
				System.out.print("历史流程定义的id:"+temp.getProcessDefinitionId());
				System.out.print("历史流程任务名称:"+temp.getName());
				System.out.println("历史流程任务处理人:"+temp.getAssignee());
			}
		}
	}
}

六、流程变量

1、涉及到的表:

act_ru_variable:正在执行的流程变量表
act_hi_varinst:流程变量历史表

2、流程变量作用
① 传递业务参数(申请人、天数、事件、原因)
② 动态指定办理人
③ 指定连接,完成任务(同意或者拒绝)

3、设置简易的bpmn流程图
4、部署流程定义及启动流程实例
5、设置流程变量:通过 TaskService 和 RuntimeService 服务设置变量
6、获取流程变量
7、查询历史的流程变量
8、流程变量支持的类型(包括了大部分封装类型和Date、String和实现了Serializable接口的类的类型)

public class AppayBillBean  implements Serializable{
	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;
	}
}
public class ProcessVariable {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();

	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("支付流程")
				.addClasspathResource("diagrams/AppayBill.bpmn")
				.addClasspathResource("diagrams/AppayBill.png")
				.deploy();
		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "appayBill";// 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());
			}
		}
	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "1502";
		// taskId:任务id
		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
	
	//设置流程变量值
	@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("设置成功!");
	}
	
	//查询流程变量
	@Test
	public void getVariable(){
		String taskId="1804";//任务id
//		TaskService taskService = processEngine.getTaskService();
//		Integer cost=(Integer) taskService.getVariable(taskId, "cost");//取变量
//		Date date=(Date) taskService.getVariable(taskId, "申请时间");//取本任务中的变量
////		Date date=(Date) taskService.getVariableLocal(taskId, "申请时间");//取本任务中的变量
//		String appayPerson=(String) taskService.getVariableLocal(taskId, "申请人");//取本任务中的变量
////		String appayPerson=(String) taskService.getVariable(taskId, "申请人");//取本任务中的变量
//		
//		System.out.println("金额:"+cost);
//		System.out.println("申请时间:"+date);
//		System.out.println("申请人:"+appayPerson);

		//读取实现序列化的对象变量数据
		TaskService taskService = processEngine.getTaskService();
		AppayBillBean appayBillBean=(AppayBillBean) taskService.getVariable(taskId, "appayBillBean");
		System.out.println(appayBillBean.getCost());
		System.out.println(appayBillBean.getAppayPerson());
	}
	
	//模拟流程变量设置
	@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);//取当前执行对象的所有变量
	}	
}

9、Execution 与 ProcessInstance 区别
① Execution:只一个流程实例具体要执行的过程对象
② ProcessInstance:流程实例 ProcessInstance(1)–>Execution(N) ,且N>=1
③ 值等情况: act_ru_execution 的id和 proc_inst_id 相同 ,该流程没有子流程
④ 值不等情况: 只会出现在子流程中(嵌套、引入),act_ru_execution 的id和 proc_inst_id 不相同,但parent_id 等于当前流程实例的 id 和proc_inst_id
⑤ 比如一个购物流程中除了下单、出库节点,可能还有一个付款子流程,一般付款流程都是作为公用的流程,当任务达到子流程时,引擎会自动创建一个付款子流程

10、setValiable 与 setLocalValiable区别:作用域

七、连线

1、设置bpmn流程图
2、部署和执行流程
3、查询和完成任务
4、如何设置条件变量
连线 > main config > condition
表达式的结果必须是布尔型: #{variable=='value'} 或者 ${variable==value}
5、总结
① 一个活动中可以指定一个或多个SequenceFlow(Start中有一个,End中没有)。
◇ 开始活动中有一个SequenceFlow
◇ 结束活动中没有SequenceFlow
◇ 其他活动中有1条或多条SequenceFlow
② 如果只有一个,则可以不使用流程变量设置codition的名称

public class SequenceFlow {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();
	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("连线流程")
				.addClasspathResource("diagrams/SequenceFlow.bpmn")
				.deploy();
		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "sequenceBill";// 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());
			}
		}
	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "2704";
		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("当前任务执行完毕");
	}
}

八、排他网关(ExclusiveGateWay)

1、设置bpmn流程图
2、部署与执行流程
3、查询和完成任务
4、总结
① 一个排他网关对应一个以上的顺序流
② 由排他网关流出的顺序流都有个conditionExpression元素,在内部维护返回boolean类型的决策结果。
③ 决策网关只会返回一条结果。当流程执行到排他网关时,流程引擎会自动检索网关出口,从上到下检索如果发现 第一条决策结果为true或者没有设置条件的(默认为成立),则流出。
④ 如果没有任何一个出口符合条件,则抛出异常
⑤ 使用流程变量,设置连线的条件,并按照连线的条件执行工作流,如果没有条件符合的条件,则以默认的连线离开,但是默认的连线不能设置条件

public class ExclusiveGetWay {
	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());
			}
		}
	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "3704";
		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("当前任务执行完毕");
	}
}

九、用户任务(userTask)

个人分配任务方式1:直接指定
个人分配任务方式2:采用流程变量(在bpmn的assignee设置 ${userID}

public class UserTask {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();

	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("用户任务指定流程")
				.addClasspathResource("diagrams/AppayBill.bpmn")
				.deploy();

		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "appayBill";// bpmn 的 process id属性
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("userID", "王某某");
		ProcessInstance pi = processEngine.getRuntimeService()
				.startProcessInstanceByKey(processDefiKey, params);
		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance
		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		String assignee="王某某";//指定任务处理人
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery
				.taskAssignee(assignee)
				.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 = "3704";
		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("当前任务执行完毕");
	}
}

十、数据库相关表

 -- 流程部署相关的表
SELECT * FROM act_ge_bytearray # 通用字节资源表
SELECT * FROM act_ge_property # 通用属性表,可以生成部署id
SELECT * FROM act_re_deployment  #部署表
SELECT * FROM act_re_procdef    # 流程定义表

-- 流程实例与任务相关的表
SELECT * FROM act_ru_execution  # 流程执行对象信息
SELECT * FROM act_ru_task   # 正在运行的任务表
SELECT * FROM act_hi_procinst # 历史流程实例表
SELECT * FROM act_hi_taskinst  # 历史流程任务表

-- 流程变量相关表
SELECT * FROM act_ru_variable # 正在执行的流程变量表
SELECT * FROM act_hi_varinst # 流程变量历史表

猜你喜欢

转载自blog.csdn.net/Mr_GaoYang/article/details/85258197