Activiti工作流--流程变量及流程定义语句

概念

流程变量在整个工作流中扮演很重要的作用。例如:请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是流程实例。也就是说各个流程实例的流程变量是不相互影响的。流程实例结束完成以后流程变量还保存在数据库中(存放到流程变量的历史表中)。

添加和设置流程变量

  1. 流程图

在这里插入图片描述

  1. 部署流程定义
	@Test
	public void deployTest() {
		//获取核心对象
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		//获取服务
		RepositoryService repositoryService = processEngine.getRepositoryService();
		//操作
		DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
		deploymentBuilder
				.name("请假流程")//设置部署名称
				.addClasspathResource("ProcessVarTest.bpmn")
				.addClasspathResource("ProcessVarTest.png");
		deploymentBuilder.deploy();	
	}


  1. 启动流程实例
	@Test
	public void  startProcessTest() throws Exception {
		//创建核心对象
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		//获取服务
		RuntimeService runtimeService = processEngine.getRuntimeService();
		String processDefinitionKey="ProcessVarTestId";
		Map<String,Object> variables=new HashMap<>();
		variables.put("剩余假期天数", 3);
		//操作:启动的时候设置流程变量
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
		System.out.println("pId="+processInstance.getId());//2501
	}
  1. 设置流程变量
@Test
	public void  setVarTest() throws Exception {
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		TaskService taskService = processEngine.getTaskService();
		String processInstanceId="2501";
		String assignee="小明";
		
		//通过任务服务获取这个流程实例中  小明的唯一的一个任务
		Task task = taskService.createTaskQuery()
		.processInstanceId(processInstanceId)//在一次流程实例中一个人的任务是唯一的
		.taskAssignee(assignee)
		.singleResult();
		System.out.println(task);
		
		//设置一个流程变量
		String taskId = task.getId();
		taskService.setVariable(taskId, "请假人", assignee);
		Map<String,Object> variables=new HashMap<>();
		variables.put("请假原因","相亲");//设置String
		variables.put("请假天数", 3);//设置Integer
		variables.put("是否扣工资",true);//设置boolean:存long型:1true;0false
		variables.put("请假开始时间", new Date());//设置Date类型
		variables.put("扣多少钱", 666.666d);//设置Double
		//设置多个流程变量:
		taskService.setVariables(taskId, variables);
		
		//完成任务的时候设置:
		Map<String,Object> variables1=new HashMap<>();
		variables1.put("老板", "亲爱的老板,我真的要回去相亲了,很急的。。。。。");
		taskService.complete(taskId, variables1);
	}

  1. 获取流程变量
@Test
	public void  getVarTest() throws Exception {
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		TaskService taskService = processEngine.getTaskService();
		String processInstanceId="2501";
		String assignee="美丽";
		//一个流程实例中,一个办理人只有一个任务
		Task task = taskService.createTaskQuery().
				processInstanceId(processInstanceId).
				taskAssignee(assignee)
				.singleResult();
		String taskId=task.getId();
		
		Map<String, Object> variables = taskService.getVariables(taskId);
		System.out.println("所有的流程变量:"+variables);
		Map<String, Object> variables2 = taskService.getVariables(taskId, Arrays.asList("请假天数","老板"));
		System.out.println("批量获取流程变量:"+variables2);
		Double money = (Double) taskService.getVariable(taskId, "扣多少钱");
		System.out.println("获取一个变量:"+money);
		Date beginDate = taskService.getVariable(taskId, "请假开始时间",Date.class);
		System.out.println("获取一个变量:"+beginDate);
	}

说明:

1)流程变量的获取针对流程实例(即1个流程),每个流程实例获取的流程变量时不同的
2)使用基本类型获取流程变量,在taskService中使用任务ID,流程变量的名称,获取流程变量的值。
3)Javabean类型设置获取流程变量,除了需要这个javabean实现了Serializable接口外,还要求流程变量对象的属性不能发生变化,否则抛出异常。解决方案,固定序列化ID

  1. 模拟流程变量的设置和获取的场景
	@Test
	public void  setVarAndGetVarTest() throws Exception {
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		RuntimeService runtimeService = processEngine.getRuntimeService();
		TaskService taskService = processEngine.getTaskService();
		//设置流程变量:4种
			//①:启动流程的时候设置
				//runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
			//②:任务完成的时候设置
				//taskService.complete(taskId, variables);
			//③:runtimeService设置
		 		//runtimeService.setVariable(executionId, variableName, value);//存一个
		 		//runtimeService.setVariables(executionId, variables);//存多个
			//④:taskService设置
				//taskService.setVariable(taskId, variableName, value);//存一个
				//taskService.setVariables(taskId, variables);//存多个
		//获取流程变量:2种
			//①:runtimeService获取变量
				//runtimeService.getVariables(executionId)//获取所有
				//runtimeService.getVariables(executionId, variableNames)//批量获取
				//runtimeService.getVariable(executionId, variableName);//获取一个,但是要强转
				//runtimeService.getVariable(executionId, variableName, variableClass)//获取一个,带泛型,不强转
			//②:taskService获取变量
				//taskService.getVariables(taskId)//获取所有
				//taskService.getVariables(taskId, variableNames)//批量获取
				//taskService.getVariable(taskId, variableName);//获取一个,但是要强转
				//taskService.getVariable(taskId, variableName, variableClass)//获取一个,带泛型,不强转
	}

流程变量类型

说明:

1)RuntimeService对象可以设置流程变量和获取流程变量
2)TaskService对象可以设置流程变量和获取流程变量
3)流程实例启动的时候可以设置流程变量
4)任务办理完成的时候可以设置流程变量
5)流程变量可以通过名称/值的形式设置单个流程变量
6)流程变量可以通过Map集合,同时设置多个流程变量 Map集合的key表示流程变量的名称 Map集合的value表示流程变量的值

流程变量类型

如图是从官网列出来的流程变量的类型:
在这里插入图片描述
从图中可以看出包括了大部分封装类型和Date、String和实现了Serializable接口的类的类型。如果想用javabean 作为流程变量,有两种情况:
1、是hibernate的实体类型(持久化类、映射文件)
主键的类型必须是long或者string
2、实现Serializable接口即可-讲解

在这里插入图片描述

1. 实现了Serializable的JavaBean

public class Person implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -3517396639445147065L;
	private Long id;
	private String name;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + "]";
	}

	public Person(Long id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
}

  1. 添加流程变量
@Test
	public void  setVarTest() throws Exception {
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		TaskService taskService = processEngine.getTaskService();
		String processInstanceId="2501";
		String assignee="小莉";
		
		//通过任务服务获取这个流程实例中  小莉的唯一的一个任务
		Task task = taskService.createTaskQuery()
		.processInstanceId(processInstanceId)//在一次流程实例中一个人的任务是唯一的
		.taskAssignee(assignee)
		.singleResult();
		System.out.println(task);
		
		//设置一个流程变量
		String taskId = task.getId();
		
		//流程变量设置java对象:
		taskService.setVariable(taskId, "我是一个java对象", new Person(1L,"大花"));
		taskService.complete(taskId);
	}

  1. 获取流程变量
@Test
	public void  getVarTest() throws Exception {
		ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
		TaskService taskService = processEngine.getTaskService();
		String processInstanceId="2501";
		String assignee="美丽";
		//一个流程实例中,一个办理人只有一个任务
		Task task = taskService.createTaskQuery().
				processInstanceId(processInstanceId).
				taskAssignee(assignee)
				.singleResult();
		String taskId=task.getId();
		Person person = taskService.getVariable(taskId, "我是一个java对象",Person.class);
		System.out.println("我是一个java对象:"+person);
	}

问题:

流程变量表没有存储taskid,那么我们之前怎么通过TaskId获取的流程变量数据??
在这里插入图片描述
分析:
在这里插入图片描述

由打印的sql可以看出,底层做了兼容,先通过taskId,如果获取不到再他通过executionId获取

总结:

设置流程变量:4种
①:启动流程的时候设置
②:任务完成的时候设置
③:runtimeService设置
④:taskService设置
获取流程变量:2种
①:runtimeService获取变量
②:taskService获取变量

注意:

1.流程变量应该可以被所有的执行对象获取(只要流程实例不结束,流程变量可以在任何地方获取)
2.流程变量是可以覆盖的
3.如果存放domain实体类的话就需要这个实体类实现序列化接口 Serializable

流程定义语言(BPMN)

业务流程建模与标注(Business Process Model and Notation,BPMN)
,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)
Eclispse画出流程,有两个文件bpmn文件和png文件,其中bpmn文件又可以叫做流程定义文件,它需要遵循BPMN语言规范.png:就是一个单纯的图片,没有任何作用.

  1. 流程(process)

bpmn文件一个流程的根元素。一个流程就代表一个工作流。

  1. 顺序流(sequenceFlow )

顺序流是连接两个流程节点的连线,代表一个节点的出口。流程执行完一个节点后,会沿着节点的所有外出顺序流继续执行。 就是说,BPMN
2.0默认的行为就是并发的: 两个外出顺序流会创造两个单独的,并发流程分支。
顺序流主要由4个属性组成:
Id: 唯一标示,用来区分不同的顺序流
sourceRef:连线的源头节点ID
targetRef:连线的目标节点ID
name(可选):连线的名称,不涉及业务,主要用于显示。多出口原则要设置。

说明:
①结束节点没有出口
②其他节点有一个或多个出口。如果有一个出口,则代表是一个单线流程;如果有多个出口,则代表是开启并发流程。

  1. 分支流程-流程图
    在这里插入图片描述

为了方便使用抽取的公共代码

package base;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ExecutionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;

/**
 * 公共代码抽取
 * @author Lenovo
 *
 */
public class BaseBpmn {
	// 获取核心对象 服务大管家
	protected ProcessEngine ProcessEngine = ProcessEngines.getDefaultProcessEngine();
	// 获取运行的service服务
	protected RuntimeService runtimeService = ProcessEngine.getRuntimeService();
	// 获取TaskService
	protected TaskService taskService = ProcessEngine.getTaskService();
	
	/**
	 * 部署文件
	 * @param resource 资源文件名,没有后缀
	 * @param name 用于设置流程名
	 */
	public void deploy(String resource, String name){
		// 获取核心对象 服务大管家
				// 获取服务
		RepositoryService repositoryService = ProcessEngine.getRepositoryService();
		// 部署对象
		DeploymentBuilder createDeployment = repositoryService.createDeployment();
		// 上传资源
		InputStream inputStream = this.getClass().getResourceAsStream(resource + ".bpmn");
		InputStream inputStream2 = this.getClass().getResourceAsStream(resource + ".png");
		createDeployment.addInputStream(resource + ".bpmn", inputStream);
		createDeployment.addInputStream(resource + ".png", inputStream2);
		createDeployment.name(name);
		// 部署
		createDeployment.deploy();
	}
	/**
	 * 启动实例,带参数
	 * @param key 
	 * @param variables 变量
	 * @return ProcessInstance 
	 */
	public ProcessInstance start(String key, Map<String, Object> variables) {
		return runtimeService.startProcessInstanceById(key, variables);
	}
	
	/**
	 * 启动实例,不带参数
	 * @param key
	 * @return ProcessInstance 
	 */
	public ProcessInstance start(String key) {
		return runtimeService.startProcessInstanceByKey(key);
	}
	/**
	 * 完成任务,带流程变量,方便流转下一个节点
	 * @param taskId 任务id
	 * @param variables  需要携带的变量
	 */
	public void compleTask(String taskId, Map<String, Object> variables){
		taskService.complete(taskId, variables);
	}
	/**
	 * 完成任务,不带参数
	 * @param taskId
	 */
	public void compleTask(String taskId){
		taskService.complete(taskId);
	}
	/**
	 * 完成任务,通过实例id和人的姓名 带参数
	 * @param 实例id
	 * @param 人的名字
	 * @param 参数
	 */
	public void compleTaskByPIdAndName(String pid, String name, Map<String, Object> variables){
		// 获取查询对象
		TaskQuery createTaskQuery = taskService.createTaskQuery();
		// 获取任务id
		Task task = createTaskQuery.processInstanceId(pid).taskAssignee(name).singleResult();
		// 完成
		taskService.complete(task.getId(),variables);
	}
	/**
	 * 完成任务,通过实例id和人的姓名
	 * @param pid 实例id
	 * @param name 人的名字
	 */
	public void compleTaskByPIdAndName(String pid, String name){
		// 获取查询对象
		TaskQuery createTaskQuery = taskService.createTaskQuery();
		// 获取任务id
		Task task = createTaskQuery.processInstanceId(pid).taskAssignee(name).singleResult();
		// 完成
		taskService.complete(task.getId());
	}
	/**
	 * 查询某个人的任务列表
	 * @param name
	 * @return list 
	 * @throws Exception
	 */
	public List<Task> queryTaskList(String name) throws Exception {
		// 获取查询对象
		TaskQuery createTaskQuery = taskService.createTaskQuery();
		// 设置查询条件
		createTaskQuery.taskAssignee(name);
		// 查询列表
		List<Task> list = createTaskQuery.list();
		return list;
	}
	/**
	 * 查询某个人的当前任务
	 * @param pid
	 * @param name
	 * @return
	 * @throws Exception
	 */
	public Task queryTaskByName(String pid, String name) throws Exception {
		// 获取查询对象
		TaskQuery createTaskQuery = taskService.createTaskQuery();
		// 设置查询条件
		createTaskQuery.taskAssignee(name);
		createTaskQuery.processInstanceId(pid);
		//
		Task task = createTaskQuery.singleResult();
		return task;
	}
	/**
	 * 查询当前活动对象(当前活动节点)
	 * @param pid
	 * @param actid
	 * @return
	 * @throws Exception
	 */
	public Execution queryExcution(String pid, String actid) throws Exception {
		// 获取查询对象
		ExecutionQuery createExecutionQuery = runtimeService.createExecutionQuery();
		// 设置查询条件
		Execution execution = createExecutionQuery.processInstanceId(pid).activityId(actid).singleResult();
		// 返回
		return execution;
	}
	public void isEnd(String pid) {
		// 查询对象
		ProcessInstanceQuery createProcessInstanceQuery = runtimeService.createProcessInstanceQuery();
		// 根据id
		ProcessInstance singleResult = createProcessInstanceQuery.processInstanceId(pid).singleResult();
		// 如果singleResult找到说明流程还没有结束
		if (singleResult != null) {
			System.out.println("流程未结束或不存在");
		} else {
			System.out.println("流程结束");
		}

	}
}

如果您觉得不错请点个赞,谢谢!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值