一、什么是BPMN
业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)
Eclispse画出流程,有两个文件bpmn文件和png文件,其中bpmn文件又可以叫做流程定义文件,它需要遵循BPMN语言规范;png:就是一个单纯的图片,没有任何作用.
二、流程(process)
bpmn文件是一个流程的根元素。一个流程就代表一个工作流。
三、公共代码抽取的工具类
针对工作流的公共代码,我这里写了一个工具类,希望能给学习工作流的朋友带来帮助,代码示例如下:
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;
public class BaseBpmn {
// 获取核心对象processEngine 服务大管家
protected ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取仓库服务对象
protected RepositoryService repositoryService = processEngine.getRepositoryService();
// 获取运行的服务对象runtimeService
protected RuntimeService runtimeService = processEngine.getRuntimeService();
// 获取任务服务对象TaskService
protected TaskService taskService = processEngine.getTaskService();
// 添加发布部署
public void deploy(String resource,String name) throws Exception {
// 获取流程发布对象
DeploymentBuilder createDeployment = repositoryService.createDeployment();
// 上传资源
InputStream inputStream = this.getClass().getResourceAsStream(resource+".bpmn");
InputStream inputStream2 = this.getClass().getResourceAsStream(resource+".png");
createDeployment.addInputStream(resource, inputStream);
createDeployment.addInputStream(resource, inputStream2);
createDeployment.name(name);
// 部署发布
createDeployment.deploy();
}
// 启动流程实例,不带流程变量
public ProcessInstance start(String key) throws Exception {
return runtimeService.startProcessInstanceByKey(key);
}
// 启动流程实例,带流程变量
public ProcessInstance start(String key,Map<String,Object> variables) throws Exception {
return runtimeService.startProcessInstanceByKey(key, variables);
}
// 获取任务列表
public List<Task> queryTask() throws Exception {
// 获取查询对象
TaskQuery createTaskQuery = taskService.createTaskQuery();
return createTaskQuery.list();
}
// 查询某个人的任务列表
public List<Task> queryTaskListByName(String name) throws Exception {
// 获取查询对象
TaskQuery createTaskQuery = taskService.createTaskQuery();
// 设置查询条件
createTaskQuery.taskAssignee(name);
// 返回查询列表
return createTaskQuery.list();
}
// 查询某个人的当前任务
public Task queryTaskByName(String pid,String name) throws Exception {
// 获取查询对象
TaskQuery createTaskQuery = taskService.createTaskQuery();
// 设置查询条件
createTaskQuery.taskAssignee(name);
createTaskQuery.processInstanceId(pid);
// 返回当前任务
return createTaskQuery.singleResult();
}
// 查询当前执行对象(当前活动节点)
public Execution queryExcution(String pid,String actId) throws Exception {
// 获取查询对象
ExecutionQuery executionQuery = runtimeService.createExecutionQuery();
// 设置查询条件
executionQuery.activityId(actId);
executionQuery.processInstanceId(pid);
// 返回当前执行对象
return executionQuery.singleResult();
}
// 完成任务 不带流程变量
public void completeTask(String taskId) throws Exception {
// 完成任务
taskService.complete(taskId);
}
// 完成任务 带流程变量 方便流转到下以个节点
public void completeTask(String taskId,Map<String,Object> variables) throws Exception {
// 完成任务
taskService.complete(taskId, variables);
}
// 完成任务 带实例id 和 人的名称
public void completeTaskByName(String pid,String name) throws Exception {
//查询出这个人的当前任务
Task task = queryTaskByName(pid,name);
// 完成任务
taskService.complete(task.getId());
}
// 完成任务 带实例id 和 人的名称 流程变量
public void completeTaskByName(String pid,String name,Map<String,Object> variables) throws Exception {
//查询出这个人的当前任务
Task task = queryTaskByName(pid,name);
// 完成任务
taskService.complete(task.getId(),variables);
}
// 查询流程是否结束
public void isEnd(String pid) throws Exception {
// 查询对象
ProcessInstanceQuery createProcessInstanceQuery = runtimeService.createProcessInstanceQuery();
// 根据实例id返回流程实例
ProcessInstance singleResult = createProcessInstanceQuery.processInstanceId(pid).singleResult();
// 如果singleResult找到说明流程还没有结束
if (singleResult != null) {
System.out.println("流程未结束或不存在");
} else {
System.out.println("流程结束");
}
}
}
四、顺序流(sequenceFlow )
1.什么是顺序流
顺序流是连接两个流程节点的连线,代表一个节点的出口。流程执行完一个节点后,会沿着节点的所有外出顺序流继续执行。 就是说,BPMN 2.0默认的行为就是并发的: 两个外出顺序流会创造两个单独的,并发流程分支。
顺序流主要由4个属性组成:
Id: 唯一标示,用来区分不同的顺序流
sourceRef:连线的源头节点ID
targetRef:连线的目标节点ID
name(可选):连线的名称,不涉及业务,主要用于显示。多出口原则要设置。
说明:
1)结束节点没有出口
2)其他节点有一个或多个出口。如果有一个出口,则代表是一个单线流程;如果有多个出口,则代表是开启并发流程。
2.分支流程-流程图
3.分支流程-测试代码
辅助代码:
@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());
}