一. 流程变量
1.流程变量是什么?
流程变量在整个工作流中扮演很重要的作用。
例如:一个请假流程,请假流程中有请假天数、请假原因等一些参数都为流程变量的范围。流程变量的作用域范围是流程实例。也就是说各 个流程实例的流程变量是不相互影响的。流程实例结束完成以后流程变量还保存在数据库中(存放到流程变量的历史表中)。
2.流程变量有什么用?
在流程中传递信息(共享信息)
3.如何设置流程变量?,如何获取流程变量?
设置流程变量有四种方式:(代码在下方)
//①:启动流程的时候设置
//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);//存多个
获取流程变量有两种方式:(代码在下方)
//①: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.流程变量应该可以被所有的执行对象获取(只要流程实例不结束,流程变量可以在任何地方获取)
2.流程变量是可以覆盖的
3.如果存放domain实体类的话就需要这个实体类实现序列化接口 Serializable
4.操作步骤:
1绘制流程定义图
2部署流程
3启动流程
4测试
i:绘制流程定义图
ii:部署流程
@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();
}
iii:启动流程:
@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);
variables.put("剩余病假天数", 10);
//操作:启动的时候设置流程变量
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
System.out.println("pId="+processInstance.getId());//2501
}
Ⅳ:测试:设置流程变量:
@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);
}
伍:获取流程变量
/**
* 获取流程变量的方式:
* @throws Exception
*/
@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
二. 流程定义语言(BPMN)
1.什么是BPMN?
业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)
Eclispse画出流程,有两个文件bpmn文件和png文件,其中bpmn文件又可以叫做流程定义文件,它需要遵循BPMN语言规范.png:就是一个单纯的图片,没有任何作用.
2.流程:(process)
bpmn文件一个流程的根元素。一个流程就代表一个工作流。
3.顺序流:(sequenceFlow)
顺序流是连接两个流程节点的连线,代表一个节点的出口。流程执行完一个节点后,会沿着节点的所有外出顺序流继续执行。 就是说,BPMN 2.0默认的行为就是并发的: 两个外出顺序流会创造两个单独的,并发流程分支。
顺序流的主要的四个属性组成:
Id: 唯一标示,用来区分不同的顺序流
sourceRef:连线的源头节点ID
targetRef:连线的目标节点ID
name(可选):连线的名称,不涉及业务,主要用于显示。多出口原则要设置。
说明: 结束节点没有出口,其他节点有一个或多个出口。如果有一个出口,则代表是一个单线流程;如果有多个出口,则代表是开启并发流程。
3.分支流程-流程图
4. 抽取公共类
public class BaseBpmn {
// 获取核心对象 服务大管家
protected ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
// 获取运行的service服务
protected RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
// 获取TaskService
protected TaskService taskService = defaultProcessEngine.getTaskService();
/**
* 部署文件
*
* @param resource
* @param name
*/
public void deploy(String resource, String name) {
// 获取核心对象 服务大管家
// 获取服务
RepositoryService repositoryService = defaultProcessEngine.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();
}
/**
* 启动实例带流程变量
*/
public ProcessInstance start(String key, Map<String, Object> variables) {
// 启动
// 设置一下变量
ProcessInstance startProcessInstanceByKey = runtimeService.startProcessInstanceByKey(key, variables);
return startProcessInstanceByKey;
}
/**
* 启动实例带流程变量
*/
public ProcessInstance start(String key) {
// 启动
// 设置一下变量
ProcessInstance startProcessInstanceByKey = runtimeService.startProcessInstanceByKey(key);
return startProcessInstanceByKey;
}
/**
* 完成任务 带流程变量 方便流转到下以个节点
*/
public void compleTask(String taskId, Map<String, Object> variables) throws Exception {
taskService.complete(taskId, variables);
}
/**
* 完成任务
*/
public void compleTask(String taskId) throws Exception {
taskService.complete(taskId);
}
/**
* 完成任务 实例id 和 人的名称
*/
public void compleTaskByPIdAndName(String pid, String name) throws Exception {
// 获取查询对象
TaskQuery createTaskQuery = taskService.createTaskQuery();
// 获取任务id
Task task = createTaskQuery.processInstanceId(pid).taskAssignee(name).singleResult();
// 完成
taskService.complete(task.getId());
}
/**
* 完成任务 实例id 和 人的名称
*/
public void compleTaskByPIdAndName(String pid, String name, Map<String, Object> variables) throws Exception {
// 获取查询对象
TaskQuery createTaskQuery = taskService.createTaskQuery();
// 获取任务id
Task task = createTaskQuery.processInstanceId(pid).taskAssignee(name).singleResult();
// 完成
taskService.complete(task.getId(), variables);
}
}
5.分支流程-测试代码:辅助代码:
@Test
public void deployTest() throws Exception {
Deployment deployment = deploy("报销申请","SequesceFlowTest");
System.out.println("deploymentId:"+deployment.getId());
}
@Test
public void startProcessTest() throws Exception {
String processDefinitionKey="SequesceFlowTest";
ProcessInstance processInstance = startProcess(processDefinitionKey);
System.out.println("ProcessInstanceId:"+processInstance.getId());//2501
}
测试驳回:
/**
* ①:先完成报销申请,
* ②:走到审批的时候,设置一个flag的流程变量为flase,驳回
* ③:回到①,在完成报销申请
* ④:审批人又得到审批审批任务
* @throws Exception
*/
@Test
public void notPassTest() throws Exception {
//①:先完成报销申请,
String processInstanceId="2501";
String assignee="小明";
Task applyTask = queryPersonalTask(processInstanceId,assignee);
System.out.println("获取申请任务:"+applyTask);
//先完成报销申请
taskService.complete(applyTask.getId());
assignee="小刚";
Task approveTask = queryPersonalTask(processInstanceId,assignee);
System.out.println("获取审批任务:"+applyTask);
// ②:走到审批的时候,设置一个flag的流程变量为flase
taskService.setVariable(approveTask.getId(),"flag", "false");
//驳回
taskService.complete(approveTask.getId());
//④:审批人又得到审批审批任务
assignee="小明";
applyTask = queryPersonalTask(processInstanceId,assignee);
System.out.println("再次获取申请任务:"+applyTask);
}
测试通过:
/**
* 通过
* @throws Exception
*/
@Test
public void passTest() throws Exception {
String processInstanceId="2501";
String assignee="小刚";
Task approveTask = queryPersonalTask(processInstanceId,assignee);
System.out.println("获取审批任务:"+approveTask);
// ②:走到审批的时候,设置一个flag的流程变量为flase
taskService.setVariable(approveTask.getId(),"flag", "true");
//通过
taskService.complete(approveTask.getId());
}
通过上面的文章希望能够帮助到你。