Activiti系列五: 流程实例及任务的执行

1、流程图

如何设计流程图在前面有介绍

2. 部署流程定义

方式一

@Test
	public void myDeploy(){
		//获得流程引擎对象
		ProcessEngine engin=ProcessEngines.getDefaultProcessEngine();
		
		//用于管理流程定义
		RepositoryService repService=engin.getRepositoryService();
		//发布流程的对象
		DeploymentBuilder deployBuilder= repService.createDeployment();
		//deployBuilder.name("请假流程2");
		deployBuilder.addClasspathResource("processes/Leave.bpmn");
		deployBuilder.addClasspathResource("processes/Leave.png");
		Deployment deploy=deployBuilder.deploy();
		
		
		System.out.println(deploy.getId());
	}

方式二

@Test
	public void myDeploy(){
		//获得流程引擎对象
		ProcessEngine engin=ProcessEngines.getDefaultProcessEngine();
		
		//以它为模板发布一个流程,所有得到的id并不是Leave.bpmn里面的
		Deployment deploy=engin.getRepositoryService().createDeployment()
				           .addClasspathResource("processes/Leave.bpmn")
				           .addClasspathResource("processes/Leave.png")
				           .deploy();
		System.out.println(deploy.getId());
	}

3. 启动流程实例

@Test
	public void startProccess(){
		ProcessEngine engin=ProcessEngines.getDefaultProcessEngine();
		//获得流程执行服务类对象
		RuntimeService runServ=engin.getRuntimeService();

		
		//启动流程
		ProcessInstance pi= runServ.startProcessInstanceByKey("leave01");
		
		System.out.println(pi.getId()+","+pi.getActivityId()+","+pi.getProcessDefinitionId()+","+pi.getProcessDefinitionKey()
		   +","+pi.getProcessDefinitionName()+","+pi.getBusinessKey()+","+pi.getName()+","+pi.getDeploymentId());
		
	}

代码中的leave01是指流程配置文件中的流程id,如图所示:

说明:启动流程实例操作的是数据库的act_ru_execution表,如果是用户任务节点,同时也会在act_ru_task添加一条记录

4. 查询我的个人任务

这里三个任务节点,分别制定了三个人,如下图所示:

这里节点任务的办理者的指定后面可以通过流程变量的方式指定,我们先在配置文件里面写死

//查看办理者的任务
	@Test
	public void queryTasks(){
		//指定办理者
		String assinger="张三";
		//获取流程引擎对象
		ProcessEngine engin=ProcessEngines.getDefaultProcessEngine();
		//获得任务管理服务类对象
		TaskService taskServ=engin.getTaskService();
		//获得taskquery对象
		TaskQuery query=taskServ.createTaskQuery().taskAssignee(assinger);
		//查询所有的task
		List<Task> taskList=query.list();
		for(Task task:taskList){
			System.out.println("taskId:"+task.getId()+",taskName:"+task.getName()+",assinger:"+task.getAssignee());
			System.out.println("***************************");
		}
		
	}

说明:

(1)因为是任务查询,所以从processEngine中应该得到TaskService

(2)使用TaskService获取到任务查询对象TaskQuery

(3)为查询对象添加查询过滤条件,使用taskAssignee指定任务的办理者(即查询指定用户的代办任务),同时可以添加分页排序等过滤条件

(4)调用list方法执行查询,返回办理者为指定用户的任务列表

(5)任务ID、名称、办理人、创建时间可以从act_ru_task表中查到。

(6)Execution与ProcessInstance见5.6和5.7章节的介绍。在这种情况下,ProcessInstance相当于Execution

(7)如果assignee属性为部门经理,结果为空。因为现在流程只到了”填写请假申请”阶段,后面的任务还没有执行,即在数据库中没有部门经理可以办理的任务,所以查询不到。

(8)一个Task节点和Execution节点是1对1的情况,在task对象中使用Execution_来表示他们之间的关系

(9)任务ID在数据库表act_ru_task中对应“ID_”列

 

附加:

在activiti任务中,主要分为两大类查询任务(个人任务和组任务):

(1)确切指定了办理者的任务,这个任务将成为指定者的私有任务,即个人任务。

(2)无法指定具体的某一个人来办理的任务,可以把任务分配给几个人或者一到 多个小组,让这个范围内的用户可以选择性(如有空余时间时)来办理这类任务,即组任务。

先知道个人任务的查询和办理,组任务的操作后面讲

5.  办理任务

//办理任务
	@Test
	public void competeTask(){
		String taskId="22506";
		//获取流程引擎对象
		ProcessEngine engin=ProcessEngines.getDefaultProcessEngine();
		engin.getTaskService().complete(taskId);
		System.out.println("当前任务办理完成了...");
	}

说明:

(1)是办理任务,所以从ProcessEngine得到的是TaskService。

(2)当执行完这段代码,再以员工的身份去执行查询的时候,会发现这个时候已经没有数据了,因为正在执行的任务中没有数据。

(3)对于执行完的任务,activiti将从act_ru_task表中删除该任务,下一个任务会被插入进来。

(4)如果流程执行到部门经理审批这个节点了,以”部门经理”的身份进行查询,可以查到结果。

(5)再执行办理任务代码,执行完以后以”部门经理”身份进行查询,没有结果。

重复第3和4步直到流程执行完。

6. 查询流程状态,判断流程正在执行,还是结束

在流程执行的过程中,创建的流程实例ID在整个过程中都不会变,当流程结束后,流程实例将会在正在执行的执行对象表中(act_ru_execution)被删除

       说明:

(1)因为是查询流程实例,所以先获取runtimeService

(2)创建流程实例查询对象,设置实例ID过滤参数

(3)由于一个流程实例ID只对应一个实例,使用singleResult执行查询返回一个唯一的结果,如果结果数量大于1,则抛出异常

(4)判断指定ID的实例是否存在,如果结果为空,则代表流程结束,实例在正在执行的执行对象表中已被删除,转换成历史数据。

7. 查询历史任务

//根据办理人查询历史记录
	public void queryHisByUser(String user){
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		ProcessEngine engine=ProcessEngines.getDefaultProcessEngine();
		HistoryService hisServ=engine.getHistoryService();
		HistoricTaskInstanceQuery hisTaskInstance= hisServ.createHistoricTaskInstanceQuery();
		List<HistoricTaskInstance> theTaskList=hisTaskInstance.taskAssigneeLike(user).list();
		for(HistoricTaskInstance taskInstance:theTaskList){
			System.out.println("任务id:"+taskInstance.getId());
			System.out.println("办理人:"+taskInstance.getAssignee());
			System.out.println("任务名称:"+taskInstance.getName());
			System.out.println("开始时间:"+sdf.format(taskInstance.getStartTime())+",结束时间:"
			              +sdf.format(taskInstance.getEndTime())
			              +",耗时(秒钟):"+taskInstance.getDurationInMillis()/1000);
		}
	}

 查询已完成的历史记录

// 根据发布编号查询已经完成的历史记录
	@Test
	public void queryHisByDeployId(String deployId) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
		HistoryService hisServ = engine.getHistoryService();
		HistoricProcessInstanceQuery processInstanceQuery=hisServ.createHistoricProcessInstanceQuery();
		List<HistoricProcessInstance> instanceList=processInstanceQuery.deploymentId(deployId).list();
		HistoricTaskInstanceQuery hisTaskInstanceQuery = hisServ.createHistoricTaskInstanceQuery();
		for(HistoricProcessInstance processInstance:instanceList){
			List<HistoricTaskInstance> theTaskList = hisTaskInstanceQuery.processInstanceId(processInstance.getId())
					                                                .orderByTaskCreateTime().asc().list();
			for (HistoricTaskInstance taskInstance : theTaskList) {
				if(taskInstance.getEndTime()!=null){
					System.out.println("任务id:" + taskInstance.getId());
					System.out.println("办理人:" + taskInstance.getAssignee());
					System.out.println("任务名称:" + taskInstance.getName());
					System.out.println("开始时间:" + sdf.format(taskInstance.getStartTime()) + ",结束时间:"
							+ sdf.format(taskInstance.getEndTime()) + ",耗时(秒钟):" + taskInstance.getDurationInMillis() / 1000);
				}
			}
			System.out.println("=========华丽的分割线====================");
		}
	}

8 获取流程图片

@Test
	public void viewImage(){
		String deployId="1";
		//获取流程引擎对象
		ProcessEngine engin=ProcessEngines.getDefaultProcessEngine();
		List<String> nameList=engin.getRepositoryService().getDeploymentResourceNames(deployId);
		String imgName=null;
		for(String theName:nameList){
			System.out.println("deployeName==>"+theName);
			if(theName.endsWith(".png")){
				imgName=theName;
			}
		}
		System.out.println("imgName==>"+imgName);
		try {
			if(imgName!=null){
				String targetPath="d:\\tmp\\"+imgName;
				InputStream is=engin.getRepositoryService().getResourceAsStream(deployId, imgName);
				FileCopyUtils.copy(is, new FileOutputStream(targetPath));
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

说明:

  1. deployId为流程部署ID
  2. 使用repositoryService的getDeploymentResourceNames方法可以获取指定部署下得所有文件的名称
  3. 使用repositoryService的getResourceAsStream方法传入部署ID和资源图片名称可以获取部署下指定名称文件的输入流
  4. 最后的有关IO流的操作,使用FileCopyUtils工具类的copy方法完成流程流程到文件的拷贝,将资源文件以流的形式输出到指定文件夹下

9. 删除流程

@Test
	public void deleteDeploy(){
		//获取流程引擎对象
		ProcessEngine engin=ProcessEngines.getDefaultProcessEngine();
		String deployId="1";
		RepositoryService repServ=engin.getRepositoryService();
		repServ.deleteDeployment(deployId, true);
		System.out.println("删除成功");
	}

说明:

  1. 因为删除的是流程定义,而流程定义的部署是属于仓库服务的,所以应该先得到RepositoryService
  2. 如果该流程定义下没有正在运行的流程,则可以用普通删除。如果是有关联的信息,用级联删除。项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。

删除key相同的所有不同版本的流程定义,如下

10 总结

Execution   执行对象

 按流程定义的规则执行一次的过程.

 对应的表:

  act_ru_execution: 正在执行的信息

  act_hi_procinst:已经执行完的历史流程实例信息

  act_hi_actinst:存放历史所有完成的活动

ProcessInstance  流程实例

 特指流程从开始到结束的那个最大的执行分支,一个执行的流程中,流程实例只有1个。

 

注意

    (1)如果是单例流程,执行对象ID就是流程实例ID

    (2)如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同

    (3)一个流程中,流程实例只有1个,执行对象可以存在多个。

 

Task 任务

 执行到某任务环节时生成的任务信息。

 对应的表:

  act_ru_task:正在执行的任务信息

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

 

猜你喜欢

转载自blog.csdn.net/wx5040257/article/details/113997278