工作流引擎
个人觉得直接理解工作流引擎概念有点难度,我们可以先通过了解工作流引擎的职责再反过来理解工作流引擎,工作流引擎一般都做两件事情:
1.定义流程,也就是给我们提供某种规范来定义规则,以及如何定义一个流程的这种规范,同事我们可以根据工作流引擎提供的相关概念来定义更为复杂的流程,这就是工作流引擎做的第一件事叫做定义流程。
2.执行流程,也就是工作流引擎需要解释这个规则,还要负责流程,它相当于流程的调度者,监控每个流程的执行情况,并将流程操作发往下一步,或者根据条件休眠或终止流程的这么一个过程就叫做执行流程。
了解完工作流引擎的这两个职责,我相信对于什么是工作流引擎一定已经有了一定的认识了,我们在用一句稍微有点官方的话来总结一下工作流引擎,工作流引擎为我们提供相关规则概念的定义,给我们提供了相关的API来调用这个引擎去执行流程。流程的操作实际上就是工作流引擎提供相关的api我们去调用它。
工作流框架与工作流引擎
上面我们提及了常见了几个工作流框架,其中现在的Activiti和JBPM5.0之前的版本都是基于ProcessEngine 工作流引擎的工作流框架;JBPM5.0开始是基于DroolsFlow为工作流引擎的工作流框架;其中OSWorkflow是以工作流引擎命名的工作流框架,所以OSWorkflow是基于OSWorkflow工作流引擎的工作流框架;ActiveBPEL是基于工作流BPEL引擎的工作流框架…….
到这里关于工作流的相关概念就介绍完了,接下来我们先了解一下我们的主角activiti的前世今生。
Activiti前世今生
Activiti 的创始人是 Tom Baeyens 说到Tom Baeyens 就不能不提他与jbpm的渊源。TomBaeyens 是 jBPM 的创始人,在 2002年,Tom Baeyens创建了基于状态机原理的jBPM流程引擎。jBPM经过了JBoss和Redhat公司之后,发展到了 jBPM 4。由于jBPM使用的是 GPL开源协议,并且与JBoss和Redhat公司的其他产品线结合的越来越紧密,对jBPM在更广泛的范围使用形成了阻碍。JBoss内部对jBPM未来版本的架构实现产生了严重的意见分歧,在2005年 Tom Baeyens离开了JBoss公司加入了Alfresco 公司,创建了使用Apache based-license V2的、独立于Alfresco产品的开源流程产品Activiti 。Activiti在2010年3月份开始启动,到了2010年12月份正式发布第一个版本,新的基于jBPM4的开源工作流系统Activiti 5.0 !所以说Activiti5是在jBPM 3、jBPM 4的基础上发展而来的,是原jBPM 的延续。
整个Activiti的生命周期经过了如下的几个步骤:1.流程部署 , 2.启动流程实例 , 3.执行流程对象(一个流程实例包含多执行对象) , 4.完成整个流程
如下就是具体代码:
package process;
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipInputStream;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
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.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import com.mysql.fabric.xmlrpc.base.Data;
public class TestProcess {
/***
* 整个Activiti的生命周期经过了如下的几个步骤:
* 1.流程部署
* 2.启动流程实例
* 3.执行流程对象(一个流程实例包含多执行对象)
* 4.完成整个流程
*/
//流程引擎ProcessEngine对象 ,所有操作都要依赖流程引擎对象
ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
//由流程引擎创建各service
RepositoryService repositoryService=processEngine.getRepositoryService();
//创建运行时服务
RuntimeService runtimeService=processEngine.getRuntimeService();
//创建任务服务
TaskService taskService=processEngine.getTaskService();
//历史任务相关的服务
HistoryService historyService=processEngine.getHistoryService();
//身份服务
IdentityService identityService=processEngine.getIdentityService();
//管理服务
ManagementService managermentService=processEngine.getManagementService();
}
1:部署流程---bpmn方式
@Test
public void deploymenyProcessDefinition(){
Deployment deployment=repositoryService//与流程定义和部署对象相关的service
.createDeployment()//创建一个部署对象
.name("activiti_Introduction")//添加部署的名称
.addClasspathResource("diagrams/simpleProcess/MyProcess.bpmn")//从classpath资源中加载文件,一次加载一个
.deploy();//部署
System.out.println("流程Id:"+deployment.getId());
System.out.println("流程名称:"+deployment.getName());
}
2:部署流程---zip方式
@Test
public void deploymenyProcessDefinition_zip(){
InputStream in=this.getClass().getClassLoader().getResourceAsStream("diagrams/simpleProcess/MyProcess.zip");
ZipInputStream zipInputStream=new ZipInputStream(in);
Deployment deployment=repositoryService//与流程定义和部署对象相关的service
.createDeployment()//创建一个部署对象
.name("activiti_Introduction")//添加部署的名称 activiti入门
.addZipInputStream(zipInputStream)
.deploy();//完成部署
System.out.println("部署流程Id:"+deployment.getId());
System.out.println("部署流程名称:"+deployment.getName());
}
3:启动流程实例
@Test
public void startProcessInstance(){
//流程定义的key
String processDedinitionKey="activiti_Introduction";
ProcessInstance pi=runtimeService //与正在执行的流程实例和执行对象相关的service
.startProcessInstanceByKey(processDedinitionKey);//通过key启动流程实例,key对应***.bpmn文件中id的属性值
System.out.println("流程实例id:"+pi.getId());
System.out.println("流程定义id:"+pi.getProcessDefinitionId());
}
4:查看流程
@Test
public void viewProcess(){
//流程定义的key
String deploymengId="801";
List
.getDeploymentResourceNames(deploymengId);
String resourceName="";
if(list!=null && list.size()>0){
for(String name:list){
if(name.indexOf(".png")>0){
resourceName=name;
}
}
}
//获取图片的输入流
InputStream is=repositoryService
.getResourceAsStream(deploymengId, resourceName);
File file=new File("D:/"+resourceName);
//将输入流的图片写入到磁盘下
//FileUtils.copy(is, file);
}
5:查看当前人的个人任务
@Test
public void findMyProcessTask(){
String assignee="张三";
List
.createTaskQuery()//创建任务查询对象
.taskAssignee(assignee)//指定个人任务查询 指定办理人
.list();//返回结果集
if(tasklist!=null && tasklist.size()>0){
for(Task task:tasklist){
System.out.println("任务Id:"+task.getId());
System.out.println("任务 名称:"+task.getName());
System.out.println("任务的创建时间:"+task.getCreateTime());
System.out.println("任务的办理人:"+task.getAssignee());
System.out.println("流程实例Id:"+task.getProcessInstanceId());
System.out.println("流程执行对象Id:"+task.getExecutionId());
System.out.println("流程定义Id:"+task.getProcessDefinitionId());
}
}
}
6:查询流程定义
@Test
public void findProcessDefinition(){
List
.createProcessDefinitionQuery()//创建一个流程定义的查询
.orderByProcessDefinitionVersion()//按照版本的升序排列
.list();//返回的结果集
if(proDefList!=null && proDefList.size()>0){
for(ProcessDefinition pd:proDefList){
System.out.println("流程定义Id:"+pd.getId());
System.out.println("流程定义名称:"+pd.getName());
System.out.println("流程定义的key:"+pd.getKey());
System.out.println("流程定义的版本:"+pd.getVersion());
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
System.out.println("部署对象Id:"+pd.getDeploymentId());
}
}
}
7:删除流程定义
@Test
public void deleteProcessDefinition(){
String deploymentId="601";
//不带级联删除
repositoryService.deleteDeployment(deploymentId);
//级联删除
repositoryService.deleteDeployment(deploymentId, true);
System.out.println("删除成功");
}
8:完成我的任务
@Test
public void completeMyProcess(){
//任务Id
String taskId="1201";
taskService.complete(taskId);
System.out.println("完成任务,任务Id为:"+taskId);
}
9:查询流程状态 (判断流程是正在执行还是结束了)
@Test
public void isProcessEnd(){
//正在执行的流程Id
String processInstanceId="1001";
ProcessInstance pi=runtimeService
.createProcessInstanceQuery() //创建流程实例查询
.processInstanceId(processInstanceId)//使用流程实例id查询
.singleResult();
if(pi==null){
System.out.println("流程已结束");
}else{
System.out.println("流程还在执行中");
}
}
10:查询历史任务
@Test
public void findHistoryTask(){
String taskAssignee="";
List
.createHistoricTaskInstanceQuery()//创建历史任务实例查询
.taskAssignee(taskAssignee)//指定历史任务的办理人
.list();
if(hisList!=null && hisList.size()>0){
for(HistoricTaskInstance hti:hisList){
System.out.println(hti.getId()+" "+hti.getName()+" "+hti.getProcessInstanceId()+" "+hti.getStartTime()+" ");
}
}
}
11:设置流程变量
@Test
public void setVariables(){
//任务Id
String taskId="2046";
taskService.setVariableLocal(taskId, "请假天数", 3); //与任务ID绑定
taskService.setVariable(taskId, "请假日期", new Data());
taskService.setVariable(taskId, "请假原因", "回家有事");
System.out.println("设置流程变量成功");
}
12:获取流程变量
@Test
public void getVarables(){
//任务Id
String taskId="2046";
//获取流程变量 使用基本数据类型
Integer days=(Integer) taskService.getVariable(taskId, "请假天数");
Date date=(Date) taskService.getVariable(taskId, "请假日期");
String leaveReason= (String) taskService.getVariable(taskId, "请假原因");
System.out.println("请假天数:"+days+" 请假时间:"+date+" 请假原因:"+leaveReason);
}