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();
}
}
说明:
- deployId为流程部署ID
- 使用repositoryService的getDeploymentResourceNames方法可以获取指定部署下得所有文件的名称
- 使用repositoryService的getResourceAsStream方法传入部署ID和资源图片名称可以获取部署下指定名称文件的输入流
- 最后的有关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("删除成功");
}
说明:
- 因为删除的是流程定义,而流程定义的部署是属于仓库服务的,所以应该先得到RepositoryService
- 如果该流程定义下没有正在运行的流程,则可以用普通删除。如果是有关联的信息,用级联删除。项目开发中使用级联删除的情况比较多,删除操作一般只开放给超级管理员使用。
删除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:已经执行完的历史任务信息