activiti工作流学习总结
来源:互联网 发布:数据挖掘的一般过程 编辑:程序博客网 时间:2024/05/16 10:31
开篇先说 此为一个初次接触工作流的小白,怀着忐忑的心情写下的,写给自己,也写给他人,很多东西我不是很明白,内心。。。,
因为我的整个学习路线就是看各种有关activiti的博客,单元测试,
,因工作的原因,需要用到工作流,公司大佬(7年开发,对于我一年的,)说 后面的开发需要用到activiti 工作流,建议你去看一看
废话不说了,(上一篇写的没有上传成功,心累,瞬间不想写了)
首先要使用,就下载activiti 地址: 百度 或者去CSDN 搜索下,可以下载相关的demo及中文手册,有助于更好的认识activiti;
简介
工作流(Workflow),指“业务过程的部分或整体在计算机应用环境下的自动化”。是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。在计算机中,工作流属于计算机支持的协同工作(CSCW)的一部分。后者是普遍地研究一个群体如何在计算机的帮助下实现协同工作的。
工作流主要解决的主要问题是:为了实现某个业务目标,利用计算机在多个参与者之间按某种预定规则自动传递文档、信息或者任务。
Activiti是一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调度。
工作流引擎
工作流引擎一般都做两件事情:
1.定义流程,也就是给我们提供某种规范来定义规则,以及如何定义一个流程的这种规范,
同时我们可以根据工作流引擎提供的相关概念来定义更为复杂的流程,这就是工作流引擎做的第一件事叫做定义流程。
2.执行流程,也就是工作流引擎需要解释这个规则,还要负责流程,它相当于流程的调度者,
监控每个流程的执行情况,并将流程操作发往下一步,或者根据条件休眠或终止流程的这么一个过程就叫做执行流程。
定义流程
流程定义是什么
ProcessDefinition(流程定义)就是一个流程的步骤说明,比如我 这个流程,申请人王三发起提交申请,李四作为部门经理进行审批,审批完成后,此申请到达下一级总经理王五,进行审批。就这么整个流程说明 就是流程定义,不过在Activiti中整个流程定义是以helloworld.bpmn与helloworld.png格式存在的。
部署流程定义
将流程定义进行部署,部署流程定义的方式有两种:
1.部署流程定义的helloworld.bpmn与helloworld.png两个文件
1. /**
2. * 部署流程定义 类路径从classpath
3. */
4. @Test
5. public void deoploymentProcessDefinition_classpath() {
6. Deployment deployment = processEngine.getRepositoryService() // 与流程定义和部署对象相关的service
7. .createDeployment()// 创建一个部署对象
8. .name("流程定义")// 添加部署的名称
9. .addClasspathResource("diagrams/helloworld.bpmn")// 从classpath的资源中加载,一次只能加载一个文件
10. .addClasspathResource("diagrams/helloworld.png")// 从classpath的资源中加载,一次只能加载一个文件
11. .deploy();// 完成部署
12. System.out.println("部署ID:" + deployment.getId());
13. System.out.println("部署名称:" + deployment.getName());
14. }
2.将helloworld.bpmn与helloworld.png压缩成zip进行部署
1. /**
2. * 部署流程定义 zip
3. */
4. @Test
5. public void deploymentProcessDefinition_zip() {
6. InputStream in = this.getClass().getClassLoader()
7. .getResourceAsStream("diagrams/helloworld.zip");
8. ZipInputStream zipInputStream = new ZipInputStream(in);
9. Deployment deployment = processEngine.getRepositoryService()// 与流程定义和部署对象相关的service
10. .createDeployment()// 创建一个部署对象
11. .name("流程定义")// 添加部署
12. .addZipInputStream(zipInputStream)// 指定zip格式的文件完成部署
13. .deploy();// 完成部署
14. System.out.println("部署ID:" + deployment.getId());
15. System.out.println("部署名称:" + deployment.getName());
16.
17. }
将上面部署的过程进行下解释:
1)先获取流程引擎对象:在创建时会自动加载classpath下的activiti.cfg.xml
2)通过获取的流程引擎对象,通过流程引擎对象获取一个RepositoryService对象(仓库对象)
3)由仓库的服务对象产生一个部署对象配置对象,用来封装部署操作的相关配置
4)这是一个链式编程,在部署配置对象中设置显示名字,上传流程定义规则文件
5)向数据库表中存放流程定义的规则信息
启动流程实例
1. /**
2. * 启动流程实例
3. */
4. @Test
5. public void startProcessInstance() {
6. // 流程定义的key
7. String processDefinitionKey = "HelloWorld";
8. ProcessInstance pi = processEngine.getRuntimeService()// 与正在执行的流程实例和执行对象相关的Service
9. .startProcessInstanceByKey(processDefinitionKey);// 使用流程定义的key启动流程实例,key对应HelloWorld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动
10. System.out.println("流程实例ID:" + pi.getId());
11. System.out.println("流程定义ID:" + pi.getProcessDefinitionId());
12. }
查询当前的个人任务
在上面讲流程启动后,因为该节点是任务节点所以在任务表中插入了任务的记录,现在我们就通过办理人将任务进行下查询:
1. /**
2. * 查询当前的个人任务
3. */
4. @Test
5. public void findMyPersonTask() {
6. String assignee = "张三"; // TODO
7. List<Task> list = processEngine.getTaskService()// 与正在执行的任务管理相关的service
8. .createTaskQuery()// 创建任务查询对象
9. // 查询条件
10. .taskAssignee(assignee)// 指定个人任务查询,指定办理人
11. // .taskCandidateGroup("")//组任务的办理人查询
12. // .processDefinitionId("")//使用流程定义ID查询
13. // .processInstanceId("")//使用流程实例ID查询
14. // .executionId(executionId)//使用执行对象ID查询
15. /** 排序 */
16. .orderByTaskCreateTime().asc()// 使用创建时间的升序排列
17. // 返回结果集
18. // .singleResult() //返回唯一的结果集
19. // .count()//返回结果集的数量
20. // .listPage(firstResult, maxResults)//分页查询
21. .list();// 返回列表
22. if (list != null && list.size() > 0) {
23. for (Task task : list) {
24. System.out.println("任务ID:" + task.getId());
25. System.out.println("任务名称:" + task.getName());
26. System.out.println("任务的创建时间:" + task.getCreateTime());
27. System.out.println("任务的办理人:" + task.getAssignee());
28. System.out.println("流程实例ID:" + task.getProcessInstanceId());
29. System.out.println("执行对象ID:" + task.getExecutionId());
30. System.out.println("流程定义ID:" + task.getProcessDefinitionId());
31. System.out
32. .println("##################################################");
33. }
说明:
1)因为是任务查询,所以从processEngine中应该得到TaskService
2)使用TaskService获取到任务查询对象TaskQuery
3)为查询对象添加查询过滤条件,使用taskAssignee指定任务的办理者(即查询指定用户的代办任务),同时可以添加分页排序等过滤条件
4)调用list方法执行查询,返回办理者为指定用户的任务列表
5)任务ID、名称、办理人、创建时间可以从act_ru_task表中查到。
6)在现在这种情况下,ProcessInstance相当于Execution
7) 一个Task节点和Execution节点是1对1的情况,在task对象中使用Execution_来表示他们之间的关系
8)任务ID在数据库表act_ru_task中对应“ID_”列
完成任务
1. /**
2. * 完成我的任务
3. */
4. @Test
5. public void compliteMyPersonTask() {
6. // 任务ID
7. String taskId = "504";
8. processEngine.getTaskService().complete(taskId);
9. ;
10. System.out.println("完成任务:任务ID:" + taskId);
11. }
说明:
1)是完成任务,所以从ProcessEngine得到的是TaskService。
2)当执行完这段代码,再以员工的身份去执行查询的时候,会发现这个时候已经没有数据了,因为正在执行的任务中没有数据。
3)对于执行完的任务,activiti将从act_ru_task表中删除该任务,下一个任务会被插入进来。
4)以”部门经理”的身份进行查询,可以查到结果。因为流程执行到部门经理审批这个节点了。
5)再执行办理任务代码,执行完以后以”部门经理”身份进行查询,没有结果。
6)重复第3和4步直到流程执行完。
查询历史任务
员工张三的任务已经完成,现在任务到部门经理李四了,如果我们现在仍然查询张三的任务的话,自然是查询不到了,只有查询李四才可以查到,不过我们可以通过流程实例id查询历史任务,查询历史任务可以将已经办理过的任务和现在正在执行的任务都查询出来:
1. /**
2. * 查询历史任务
3. */
4. @Test
5. public void findHistoryTask(){
6. String processInstanceId="501";
7. List<HistoricTaskInstance> list = processEngine.getHistoryService()//与历史数据(历史表)相关的service
8. .createHistoricTaskInstanceQuery()//创建历史任务实例查询
9. .processInstanceId(processInstanceId)
10. // .taskAssignee(taskAssignee)//指定历史任务的办理人
11. .list();
12. if(list!=null && list.size()>0){
13. for(HistoricTaskInstance hti:list){
14. System.out.println(hti.getId()+" "+hti.getName()+" "+hti.getProcessInstanceId()+" "+hti.getStartTime()+" "+hti.getEndTime()+" "+hti.getDurationInMillis());
15. System.out.println("################################");
16. }
17. }
18.
19. }
查询流程是否结束
我们还可以通过流程实例id查询某个流程现在的状态,是仍然在执行过程中呢,还是流程执行已经结束:
1. /**
2. * 查询流程状态(判断流程正在执行,还是结束)
3. */
4. @Test
5. public void isProcessEnd(){
6. String processInstanceId = "501";
7. ProcessInstance pi = processEngine.getRuntimeService()//表示正在执行的流程实例和执行对象
8. .createProcessInstanceQuery()//创建流程实例查询
9. .processInstanceId(processInstanceId)//使用流程实例ID查询
10. .singleResult();
11.
12. if(pi==null){
13. System.out.println("流程已经结束");
14. }
15. else{
16. System.out.println("流程没有结束");
17. }
18.
19. }
流程变量使用的范围,流程变量的作用域范围是只对应一个流程实例。也就是说各个流程实例的流程变量是不互相影响
设置流程变量
taskService.setVariableLocal(taskId, "请假原因", "回去探亲,一起吃个饭123");
获取流程变量
String reason = (String) taskService.getVariable(taskId, "请假原因");
使用javabean
1. Person p = new Person();
2. p.setName("翠花");
3. p.setId(20);
4. p.setDate();;
5. p.setNote("回去探亲,一起吃个饭123");
taskService.setVariable(taskId, "人员信息(添加固定版本)", p);
获取流程变量
Person p = (Person)taskService.getVariable(taskId, "人员信息(添加固定版本)");
整个流程:
编写流程定义文件
部署流程定义
启动流程实例
查询领取完成任务
任务完成,流程实例结束
部分代码
FinancialReportProcess.bpmn20.xml
<definitions id="definitions"
targetNamespace="http://activiti.org/bpmn20"
xmlns:activiti="http://activiti.org/bpmn"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
<process id="financialReport" name="Monthly financial report reminder process">
<startEvent id="theStart" />
<sequenceFlow id='flow1' sourceRef='theStart' targetRef='writeReportTask' />
<userTask id="writeReportTask" name="Write weekly newspapers" >
<documentation>
Write monthly financial report for publication to shareholders.
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>accountancy</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id='flow2' sourceRef='writeReportTask' targetRef='verifyReportTask' />
<userTask id="verifyReportTask" name="Verify weekly newspapers" >
<documentation>
Verify monthly financial report composed by the accountancy department.
This financial report is going to be sent to all the company shareholders.
经理审批周报,流程结束了
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id='flow3' sourceRef='verifyReportTask' targetRef='theEnd' />
<endEvent id="theEnd" />
</process>
</definitions>
Test
@Test
public void copytest(){
// 部署流程定义 Deploy the process definition
repositoryService.createDeployment()
.addClasspathResource("FinancialReportProcess.bpmn20.xml")
.deploy();
// 启动流程实例 bykey 这里的key 为 流程定义文件里流程的id
String procId = runtimeService.startProcessInstanceByKey("financialReport").getId();
System.out.println("流程实例id"+procId);
// 获取第一个任务 Get the first task
// 首先获取任务服务
TaskService taskService = processEngine.getTaskService();
// 根据分组获取任务 当前组可以填写请假单
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
// System.out.println("accountancy组,可领取的任务数量"+taskService.createTaskQuery().taskCandidateGroup("accountancy").count());
for (Task task : tasks) {
System.out.println("以下任务可用于 开发小组: " +task.getName());
// 申领 claim it
taskService.claim(task.getId(),"fozzie");
System.out.println("领取——填写周报");
}
// 验证Fozzie获取了任务 VerifyFozzie can now retrieve the task
tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
for (Task task : tasks) {
System.out.println("Task for fozzie: " +task.getName());
System.out.println(" fozzie的任务: " +task.getName());
// 完成任务 Complete the task
taskService.complete(task.getId());
System.out.println("完成任务!——周报填写完成,并提交到经理那边等待审批");
}
System.out.println("任务数量 —— fozzie: "
+ taskService.createTaskQuery().taskAssignee("fozzie").count());
// System.out.println("任务数量 —— fozzie: "
// + taskService.createTaskQuery().taskAssignee("小白").count());
/**经理暂时不处理任务,查看历史任务**/
// 获取并申领第二个任务 Retrieve and claim the second task
tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
System.out.println("以下任务用于—— 经理组: " +task.getName());
taskService.claim(task.getId(),"kermit");
System.out.println("经理 领取审批任务");
}
// 完成第二个任务并结束流程 Completing the second task ends the process
for (Task task : tasks) {
taskService.complete(task.getId());
System.out.println("审批完成,整个流程结束");
}
// 验证流程已经结束 verify that the process is actually finished
HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance =
historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(procId)
.singleResult();
System.out.println("Process instance end time,流程实例结束时间: "
+ historicProcessInstance.getEndTime());
}
- activiti工作流学习总结
- Activiti工作流学习总结
- Activiti工作流学习总结
- Activiti工作流学习总结(一)
- Activiti工作流学习总结数据结构(二)
- 工作流引擎Activiti学习 --- 小小总结
- Activiti工作流学习总结(二)
- 工作流Activiti的学习总结(五) activiti的API和虚拟工作流测试
- Activiti工作流学习网站
- Activiti工作流学习笔记
- activiti工作流学习笔记
- 工作流Activiti的学习总结- 整合spring mvc
- 工作流Activiti的学习总结- 整合简单的一个流程
- 工作流Activiti的学习总结(十二) activiti官方十分钟快速学习
- 工作流Activiti的学习总结(十二) activiti官方十分钟快速学习
- 工作流引擎Activiti使用总结
- 工作流引擎Activiti使用总结
- 工作流引擎Activiti使用总结
- Linux的Bash变量
- 数据流图
- bzoj1728[Usaco2006 Open]Two-Headed Cows 双头牛 二分+染色
- Android多渠道打包实现不同的功能模块
- EF Attatch()方法附加对象
- activiti工作流学习总结
- 各个算法的时间复杂度和空间复杂度分析
- Java+Selenium3方法篇12-findElement之By TagName
- EMV规范(六)——处理限制
- [leetcode]: 69. Sqrt(x)
- Mentor Graphics Calibre 2017.1 Linux 1DVD寄生參數萃取
- 练习输出菱形图案
- 图像放缩中最近邻插值和双线性插值的基本原理
- 2017年JavaScript框架---Top5